亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

關(guān)于C語言中弱符號與弱引用的實際應(yīng)用問題

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

在這里插入圖片描述

最近在學(xué)習(xí)《程序員的自我修養(yǎng)——鏈接、裝載與庫》時,get到了一個新的知識點:弱符號與弱引用。書中簡短的介紹,讓我了解到弱符號的含義以及使用方式。了解我的朋友,應(yīng)該知道我喜歡將知識點與我們實際工作結(jié)合起來,在工作中利用起來,正所謂學(xué)以善用。根據(jù)我的理解,覺得利用弱符號的特性可以幫組我們在工作中編寫出更加穩(wěn)定,可復(fù)用,可組合的優(yōu)秀代碼。在此向大家分享。

符號重定義錯誤

在編碼過程中,我們經(jīng)常遇到符號重定義的錯誤。編譯器會報如下錯誤:

multiple definition of `xxx';

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

例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 則會報重定義錯誤。因為在main.c 和strong.c 文件中,整型變量strong是全局變量,它們的作用域都是跨文件的。若是在不同的作用域,即使相同變量名,也不會報錯。編譯器會有默認(rèn)的優(yōu)先級處理:總是更小作用域的變量覆蓋更大作用域的變量,前提是這兩個變量的作用域是包含或被包含的關(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 不再報錯。此時main.c 中的strong 變量的作用域是跨文件,而strong.c中的strong變量的作用域僅限strong.c文件。因此不存在相同作用域中,符號重定義問題。并且結(jié)果輸出為0;
同理,下面的代碼會編譯報錯嗎?輸出為多少呢?

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語言中,我們可以簡單地認(rèn)為花括號是文件內(nèi)作用域的分隔符。

強(qiáng)符號與弱符號

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

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

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

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

編譯并不會出錯,并且輸出為2;

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

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

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

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

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

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

小節(jié)

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

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

強(qiáng)符號替換弱符號

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

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

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

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

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

但是這樣的業(yè)務(wù)代碼,我覺得是非常差的。比如新的項目中,不需要做解密包操作了,(理論上libsdk.so庫中應(yīng)該不具備decode接口了),這樣就會導(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īng)用的文章就介紹到這了,更多相關(guān)C語言弱符號與弱引用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • wxWidgets實現(xiàn)圖片和文件按鈕

    wxWidgets實現(xiàn)圖片和文件按鈕

    這篇文章主要為大家詳細(xì)介紹了wxWidgets實現(xiàn)圖片和文件按鈕,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C語言?智能指針?shared_ptr?和?weak_ptr

    C語言?智能指針?shared_ptr?和?weak_ptr

    這篇文章主要介紹了C語言?智能指針?shared_ptr?和?weak_ptr,weak_ptr引入可以解決shared_ptr交叉引用時無法釋放資源的問題,下面來學(xué)習(xí)具體相關(guān)內(nèi)容吧,需要的朋友可以參考一下
    2022-04-04
  • C語言實現(xiàn)的猜數(shù)字小游戲

    C語言實現(xiàn)的猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)的猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • C語言數(shù)據(jù)結(jié)構(gòu)之循環(huán)鏈表的簡單實例

    C語言數(shù)據(jù)結(jié)構(gòu)之循環(huán)鏈表的簡單實例

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之循環(huán)鏈表的簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 鏈接庫動態(tài)鏈接庫詳細(xì)介紹

    鏈接庫動態(tài)鏈接庫詳細(xì)介紹

    靜態(tài)鏈接庫.lib和動態(tài)鏈接庫.dll。其中動態(tài)鏈接庫在被使用的時候,通常還提供一個.lib,稱為引入庫,它主要提供被Dll導(dǎo)出的函數(shù)和符號名稱,使得鏈接的時候能夠找到dll中對應(yīng)的函數(shù)映射
    2012-11-11
  • 記錄一個C++在條件查詢時遇到的問題(推薦)

    記錄一個C++在條件查詢時遇到的問題(推薦)

    這篇文章主要介紹了記錄一個C++在條件查詢時遇到的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • C語言 數(shù)據(jù)結(jié)構(gòu)之中序二叉樹實例詳解

    C語言 數(shù)據(jù)結(jié)構(gòu)之中序二叉樹實例詳解

    這篇文章主要介紹了C語言 數(shù)據(jù)結(jié)構(gòu)之中序二叉樹實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • 淺析如何在c語言中調(diào)用Linux腳本

    淺析如何在c語言中調(diào)用Linux腳本

    如何在c語言中調(diào)用Linux腳本呢?下面小編就為大家詳細(xì)的介紹一下吧!需要的朋友可以過來參考下
    2013-08-08
  • 基于list循環(huán)刪除元素,迭代器失效的問題詳解

    基于list循環(huán)刪除元素,迭代器失效的問題詳解

    下面小編就為大家?guī)硪黄趌ist循環(huán)刪除元素,迭代器失效的問題詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • C++超詳細(xì)分析順序表

    C++超詳細(xì)分析順序表

    程序中經(jīng)常需要將一組數(shù)據(jù)元素作為整體管理和使用,需要創(chuàng)建這種元素組,用變量記錄它們,傳進(jìn)傳出函數(shù)等。一組數(shù)據(jù)中包含的元素個數(shù)可能發(fā)生變化,順序表則是將元素順序地存放在一塊連續(xù)的存儲區(qū)里,元素間的順序關(guān)系由它們的存儲順序自然表示
    2022-03-03

最新評論