一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - 關于C語言中弱符號與弱引用的實際應用問題

關于C語言中弱符號與弱引用的實際應用問題

2022-01-10 15:03有態度的程序員 C/C++

在編碼過程中,我們經常遇到符號重定義的錯誤問題,本文通過實例代碼展示給大家介紹了C語言弱符號與弱引用的實際應用問題,一起看看吧

關于C語言中弱符號與弱引用的實際應用問題

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

符號重定義錯誤

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

multiple definition of `xxx';

這就是符號重復定義導致的,再往細里面說,是在同一作用域內符號沖突。我們知道變量是由作用域生命周期概念的。比如:

?
1
2
3
4
5
6
7
8
9
10
11
例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是全局變量,它們的作用域都是跨文件的。若是在不同的作用域,即使相同變量名,也不會報錯編譯器會有默認的優先級處理:總是更小作用域的變量覆蓋更大作用域的變量,前提是這兩個變量的作用域是包含或被包含的關系。比如:

?
1
2
3
4
5
6
7
8
9
10
11
例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文件。因此不存在相同作用域中,符號重定義問題。并且結果輸出為0;
同理,下面的代碼會編譯報錯嗎?輸出為多少呢?

?
1
2
3
4
5
6
7
8
9
10
11
main.c
int strong=0;
int main()
{
    int strong=2;
    printf("strong = %d\n",strong);
    return 0;
}
 
strong.c
static int strong=1;

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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語言中,我們可以簡單地認為花括號是文件內作用域的分隔符。

強符號與弱符號

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

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

很明顯,例1 則是出現多個強符號,導致的redefinition 錯誤。例如下面code:

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

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

強引用與弱引用

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

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

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

?
1
2
3
4
5
6
7
8
9
main.c
static __attribute__((weakref("foo"))) void myfoo(void);
void main(void)
{
    if(myfoo)
    {
        myfoo();
    }
}

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

小節

經過上面的描述,我們了解到了強符號,弱符號,強引用,弱引用的概念。我認為起碼有兩點特性可以在我們工作中使用:

  • 強符號可以替換弱符號。
  • 弱引用可以避免函數未定義的錯誤。

強符號替換弱符號

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
用戶業務流程
...
pass();
...
verify();
...
decode();
...
install();
...
report();
...

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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);
 
用戶業務流程
...
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");
...

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

到此這篇關于C語言中弱符號與弱引用的實際應用的文章就介紹到這了,更多相關C語言弱符號與弱引用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/xieyihua1994/article/details/120342319

延伸 · 閱讀

精彩推薦
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
主站蜘蛛池模板: 国产极品麻豆91在线 | 欧美精品一区二区在线观看播放 | 亚洲成人精品久久 | 色悠久久久久综合网小说 | 国产一精品一av一免费爽爽 | 蜜月aⅴ免费一区二区三区 蜜桃影像传媒推广 | 精品久久日日躁夜夜躁AV | 欧洲美女人牲交一级毛片 | 亚洲欧美专区 | 日日草视频 | 91国产在线播放 | 王雨纯 羞羞 | 欧美洲大黑香蕉在线视频 | 男男gaygays黑人| 午夜国产小视频 | 韩国三级做爰 | 久久热r在线视频精品 | 91精品国产综合久久消防器材 | 日产中文乱码卡一卡二 | 美女校花被调教出奶水 | 亚洲男人第一天堂 | 国产亚洲精品自在线亚洲情侣 | 脱jk裙的美女露小内内无遮挡 | 四虎永久网址影院 | 日本高清色视影www日本 | 日韩在线 在线播放 | 成人欧美一区二区三区 | 俄罗斯一级毛片免费播放 | 国产精品亚洲片夜色在线 | 性xxx欧美 | 小小水蜜桃视频高清在线播放 | 国产精品露脸国语对白河北 | 成人无高清96免费 | 催奶师小说| 日本加勒比一区 | 好紧好爽的午夜寂寞视频 | 日韩风月片| 日本粉色视频 | 国产香蕉国产精品偷在线观看 | 百合互慰吃奶互揉漫画 | jux629三浦理惠子在线播放 |