最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于C語(yǔ)言中弱符號(hào)與弱引用的實(shí)際應(yīng)用問(wèn)題

 更新時(shí)間:2021年09月19日 11:12:20   作者:有態(tài)度的程序員  
在編碼過(guò)程中,我們經(jīng)常遇到符號(hào)重定義的錯(cuò)誤問(wèn)題,本文通過(guò)實(shí)例代碼展示給大家介紹了C語(yǔ)言弱符號(hào)與弱引用的實(shí)際應(yīng)用問(wèn)題,一起看看吧

在這里插入圖片描述

最近在學(xué)習(xí)《程序員的自我修養(yǎng)——鏈接、裝載與庫(kù)》時(shí),get到了一個(gè)新的知識(shí)點(diǎn):弱符號(hào)與弱引用。書中簡(jiǎn)短的介紹,讓我了解到弱符號(hào)的含義以及使用方式。了解我的朋友,應(yīng)該知道我喜歡將知識(shí)點(diǎn)與我們實(shí)際工作結(jié)合起來(lái),在工作中利用起來(lái),正所謂學(xué)以善用。根據(jù)我的理解,覺(jué)得利用弱符號(hào)的特性可以幫組我們?cè)诠ぷ髦芯帉懗龈臃€(wěn)定,可復(fù)用,可組合的優(yōu)秀代碼。在此向大家分享。

符號(hào)重定義錯(cuò)誤

在編碼過(guò)程中,我們經(jīng)常遇到符號(hào)重定義的錯(cuò)誤。編譯器會(huì)報(bào)如下錯(cuò)誤:

multiple definition of `xxx';

這就是符號(hào)重復(fù)定義導(dǎo)致的,再往細(xì)里面說(shuō),是在同一作用域內(nèi)符號(hào)沖突。我們知道變量是由作用域生命周期概念的。比如:

例1:
main.c
int strong=0;
int main()
{
	printf("strong = %d\n",strong);
	return 0;
}

strong.c
int strong=1;

gcc main.c strong.c -o main 則會(huì)報(bào)重定義錯(cuò)誤。因?yàn)樵趍ain.c 和strong.c 文件中,整型變量strong是全局變量,它們的作用域都是跨文件的。若是在不同的作用域,即使相同變量名,也不會(huì)報(bào)錯(cuò)。編譯器會(huì)有默認(rèn)的優(yōu)先級(jí)處理:總是更小作用域的變量覆蓋更大作用域的變量,前提是這兩個(gè)變量的作用域是包含或被包含的關(guān)系。比如:

例2:
main.c
int strong=0;
int main()
{
	printf("strong = %d\n",strong);
	return 0;
}

strong.c
static int strong=1;

gcc main.c strong.c -o main 不再報(bào)錯(cuò)。此時(shí)main.c 中的strong 變量的作用域是跨文件,而strong.c中的strong變量的作用域僅限strong.c文件。因此不存在相同作用域中,符號(hào)重定義問(wèn)題。并且結(jié)果輸出為0;
同理,下面的代碼會(huì)編譯報(bào)錯(cuò)嗎?輸出為多少呢?

main.c
int strong=0;
int main()
{
	int strong=2;
	printf("strong = %d\n",strong);
	return 0;
}

strong.c
static int strong=1;

甚至于下面的代碼也是合法的:

main.c
int strong=0;
int main()
{
	int strong=2;
	if(1)
	{
		int strong=3;
	}
	{	
		int strong = 4;
		printf("strong = %d\n",strong);
	}
	return 0;
}

在C語(yǔ)言中,我們可以簡(jiǎn)單地認(rèn)為花括號(hào)是文件內(nèi)作用域的分隔符。

強(qiáng)符號(hào)與弱符號(hào)

編譯器默認(rèn)函數(shù)和已初始化的全局變量為強(qiáng)符號(hào),而未初始化的全局變量為弱符號(hào);同時(shí)開發(fā)者可以通過(guò)"attribute((weak))"來(lái)聲明一個(gè)符號(hào)為弱符號(hào);
gcc 在編譯過(guò)程中,對(duì)于強(qiáng)弱符號(hào)遵循一定規(guī)則進(jìn)行取舍:

  • 當(dāng)有多個(gè)為強(qiáng)符號(hào)時(shí),報(bào)"redefinition of ‘xxx'"錯(cuò)誤
  • 當(dāng)僅有一個(gè)為強(qiáng)符號(hào)時(shí),選取強(qiáng)符號(hào)的值
  • 當(dāng)都為弱符號(hào)時(shí),選擇其中暫用空間較大的符號(hào)。(防止溢出越界等問(wèn)題)—— 這個(gè)應(yīng)該和編譯器有關(guān),我在本地環(huán)境中,是不允許多個(gè)類型不同的弱符號(hào)存在的。編譯會(huì)出錯(cuò)。

很明顯,例1 則是出現(xiàn)多個(gè)強(qiáng)符號(hào),導(dǎo)致的redefinition 錯(cuò)誤。例如下面code:

main.c
int strong;
int strong=2;
int main()
{
	printf("strong = %d\n",strong);
	return 0;
}

編譯并不會(huì)出錯(cuò),并且輸出為2;

強(qiáng)引用與弱引用

我們知道在編譯成可執(zhí)行文件時(shí),若源文件引用了外部目標(biāo)文件的符號(hào),在鏈接過(guò)程中,需要找到對(duì)應(yīng)的符號(hào)定義,若未找到對(duì)應(yīng)符號(hào)(未定義),鏈接器會(huì)報(bào)符號(hào)位未定義錯(cuò)誤,導(dǎo)致編譯出錯(cuò)。這種被稱為強(qiáng)引用。與相對(duì)應(yīng)的時(shí)弱引用(開發(fā)者可通過(guò)attribute((weakref))聲明),鏈接器在鏈接符號(hào)過(guò)程中,若發(fā)現(xiàn)符號(hào)為弱引用,即使沒(méi)有找到符號(hào)定義,鏈接時(shí)也不會(huì)報(bào)錯(cuò),但是會(huì)將該引用默認(rèn)為0
書中的代碼如下:

main.c
int strong;
int strong=2;
int main()
{
	printf("strong = %d\n",strong);
	return 0;
}

雖然沒(méi)有定義foo(),但是我們可以將它編譯成可執(zhí)行文件,并且GCC 編譯不會(huì)報(bào)鏈接錯(cuò)誤,但是當(dāng)我們運(yùn)行時(shí),會(huì)發(fā)生運(yùn)行錯(cuò)誤。實(shí)際上新版本的編譯器上訴的代碼會(huì)在鏈接時(shí)報(bào)錯(cuò)的,新版本的示例代碼應(yīng)該如下:(新版本的weakref 需要函數(shù)別名,且必須是static 修飾)

main.c
static __attribute__((weakref("foo"))) void myfoo(void);
void main(void)
{
	if(myfoo)
	{
		myfoo();
	}
}

新版的弱符號(hào)引用如上所示。即表示若沒(méi)有找到foo函數(shù),編譯不報(bào)錯(cuò),但是會(huì)默認(rèn)myfoo為NULL。若在其他庫(kù)中定義了foo函數(shù),對(duì)myfoo的引用就相當(dāng)于對(duì)foo的引用。這種弱引用在庫(kù)的使用上十分有用的。

小節(jié)

經(jīng)過(guò)上面的描述,我們了解到了強(qiáng)符號(hào),弱符號(hào),強(qiáng)引用,弱引用的概念。我認(rèn)為起碼有兩點(diǎn)特性可以在我們工作中使用:

  • 強(qiáng)符號(hào)可以替換弱符號(hào)。
  • 弱引用可以避免函數(shù)未定義的錯(cuò)誤。

強(qiáng)符號(hào)替換弱符號(hào)

一些庫(kù)中對(duì)外接口可以聲明為弱符號(hào)。比如:
在math庫(kù)中,我們發(fā)現(xiàn)add(int num1, int num2)這個(gè)接口存在問(wèn)題,那我們解決方式一般有以下幾種:
1. 實(shí)現(xiàn)一個(gè)myadd(int num1,int num2)接口,之后再將項(xiàng)目中的所有add,替換為myadd。這種方式可行,但是存在缺點(diǎn):修改量大,并且后續(xù)人員不清楚背景,很有可能繼續(xù)使用熟悉的add接口。
2. 更新math庫(kù),從更本解決此問(wèn)題。這種方式比較推薦。但是也并不是通用的,比如有些庫(kù)并不是開源的,并且已經(jīng)過(guò)了支持日期,也就不適用了。

此時(shí),我們可以自己在項(xiàng)目中定義一個(gè)add(int num1,int num2)接口,用強(qiáng)符號(hào)替換庫(kù)中的弱符號(hào),這樣改動(dòng)是比較小的。(這種情景需要了解接口的實(shí)現(xiàn)內(nèi)容,可給調(diào)用者較高的重構(gòu)權(quán)力)

巧用弱引用提高代碼的健壯性

應(yīng)用層的開發(fā),離不開sdk的提供,一般sdk維護(hù)了,即使應(yīng)用沒(méi)有需求發(fā)生,往往也會(huì)為了配合sdk,進(jìn)行簡(jiǎn)單的修改。以設(shè)備升級(jí)作為舉例,若升級(jí)過(guò)程中,分為傳包(pass),驗(yàn)簽(verify),解密(decode),安裝(install),上傳日志(report)等步驟,并且這些核心接口都是以libsdk.so庫(kù)的形式提供給應(yīng)用工程師。那么正常情況下,應(yīng)用邏輯大致如下:

用戶業(yè)務(wù)流程
...
pass();
...
verify();
...
decode();
...
install();
...
report();
...

但是這樣的業(yè)務(wù)代碼,我覺(jué)得是非常差的。比如新的項(xiàng)目中,不需要做解密包操作了,(理論上libsdk.so庫(kù)中應(yīng)該不具備decode接口了),這樣就會(huì)導(dǎo)致應(yīng)用程序編譯失敗。undefine 'decode'。
因此我建議應(yīng)用代碼可以如下:

static __attribute__((weakref("pass"))) void mypass(void);
static __attribute__((weakref("verify"))) void myverify(void);
static __attribute__((weakref("decode"))) void mydecode(void);
static __attribute__((weakref("install"))) void myinstall(void);
static __attribute__((weakref("report"))) void myreport(void);

用戶業(yè)務(wù)流程
...
if(mypass)
	mypass();
else
	printf("don't need pass\n");
...
if(myverify)
	myverify();
else
	printf("don't need verify\n");
...
if(mydecode)
	mydecode();
else
	printf("don't need decode\n");
...
if(myinstall)
	myinstall();
else
	printf("don't need install\n");
...
if(myreport)
	myreport();
else
	printf("don't need report\n");
...

以上便是我理解的內(nèi)容,希望能引起的你的共鳴,如果你有好的想法,也可以和我一起分享。。。

到此這篇關(guān)于C語(yǔ)言中弱符號(hào)與弱引用的實(shí)際應(yīng)用的文章就介紹到這了,更多相關(guān)C語(yǔ)言弱符號(hào)與弱引用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解C++函數(shù)棧幀

    深入理解C++函數(shù)棧幀

    本文主要介紹了C++函數(shù)棧幀,詳細(xì)的介紹了C++函數(shù)棧幀的概念以及使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++類常量和類枚舉

    C++類常量和類枚舉

    這篇文章主要介紹了C++類常量和類枚舉,給類當(dāng)中定義一些常量,可以給所有類的對(duì)象使用,比如說(shuō)我們?cè)陬惍?dāng)中定義一個(gè)數(shù)組,希望可以定義一個(gè)常量,用來(lái)初始化數(shù)組的長(zhǎng)度,那么下面我i嗎就來(lái)看看過(guò)程當(dāng)如何吧
    2022-01-01
  • C++整數(shù)拼接技巧大揭秘

    C++整數(shù)拼接技巧大揭秘

    C++整數(shù)拼接技巧大揭秘,讓你的代碼更簡(jiǎn)潔高效!你是否還在為如何優(yōu)雅地將整數(shù)拼接成字符串而煩惱?本指南將為你揭示C++中最實(shí)用、最酷炫的整數(shù)拼接技巧,助你提升編程技能,需要的朋友可以參考下
    2024-03-03
  • 快速了解Boost.Asio 的多線程模型

    快速了解Boost.Asio 的多線程模型

    這篇文章主要介紹了Boost.Asio 的多線程模型的相關(guān)知識(shí),文中代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • c++ 類中const成員變量的賦值方法

    c++ 類中const成員變量的賦值方法

    下面小編就為大家?guī)?lái)一篇c++ 類中const成員變量的賦值方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • C++ float轉(zhuǎn)std::string 小數(shù)位數(shù)控制問(wèn)題

    C++ float轉(zhuǎn)std::string 小數(shù)位數(shù)控制問(wèn)題

    這篇文章主要介紹了C++ float轉(zhuǎn)std::string 小數(shù)位數(shù)控制問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 解析sizeof, strlen, 指針以及數(shù)組作為函數(shù)參數(shù)的應(yīng)用

    解析sizeof, strlen, 指針以及數(shù)組作為函數(shù)參數(shù)的應(yīng)用

    本篇文章是對(duì)sizeof, strlen, 指針以及數(shù)組作為函數(shù)參數(shù)的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++實(shí)現(xiàn)Linux下彈出U盤的方法

    C++實(shí)現(xiàn)Linux下彈出U盤的方法

    這篇文章主要介紹了C++實(shí)現(xiàn)Linux下彈出U盤的方法,實(shí)例分析了C++在Linux平臺(tái)上進(jìn)行IO操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • Qt中利用QTextBrowser控件設(shè)計(jì)日志窗口

    Qt中利用QTextBrowser控件設(shè)計(jì)日志窗口

    本文主要介紹了Qt中利用QTextBrowser控件設(shè)計(jì)日志窗口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • C++中this指針用法詳解及實(shí)例

    C++中this指針用法詳解及實(shí)例

    這篇文章主要介紹了C++中this指針用法詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-04-04

最新評(píng)論

子长县| 天全县| 龙州县| 剑阁县| 岫岩| 伊金霍洛旗| 渝北区| 常德市| 茂名市| 宜黄县| 乐陵市| 谷城县| 昆山市| 新和县| 绥宁县| 凌源市| 曲麻莱县| 师宗县| 永丰县| 涿州市| 洛浦县| 博爱县| 湘西| 盐边县| 肥乡县| 汨罗市| 克拉玛依市| 恩平市| 三都| 宁化县| 安多县| 集安市| 湘潭市| 舟曲县| 饶阳县| 张家港市| 陇川县| 灯塔市| 颍上县| 郧西县| 潼南县|