C語言中的強符號與弱符號

2021-09-19 08:36:35 字數 2934 閱讀 1449

參考《程式設計師的自我修養》

參考 c語言中的強符號與弱符號

main.c

int a = 100;

int main()

other.c

int a = 10;
編譯

gcc main.c other.c
編譯結果

ld: 1 duplicate symbol for architecture x86_64

clang: error: linker command failed with exit code 1

multiple definition of `a'
這種符號的定義可以被稱為強符號(strong symbol)

函式,初始化了的全域性變數為強符號

未初始化的全域性變數為弱符號

注意下面的__attribute__((weak))是gcc提供的將強符號轉為弱符號的關鍵字

main.c

extern int ext;  

int weak1;

int strong = 1;

int __attribute__((weak)) weak2 = 2;

int main()

test.c

int weak1 = 100;

//int strong = 100; //multiple definition of `strong'

int weak2 = 200;

編譯gcc mainc test.c

結果

100,100,200

這裡有人會將強符號理解為extern,因為在mainc和test.c兩個模組中共享全域性變數,你可以列印位址(位址是一樣的)。

但兩者是本質不同的

extern 本質就是宣告變數,告訴linker去其他模組找定義。

而強符號和弱符號可是實打實的定義。雖然我們說弱符號沒有初始化。

關於定義與宣告的區別,請看這篇文章c語言的定義與宣告

說實話,我也是看了《程式設計師的自我修養》之後,才知道有強符號和弱符號的概念,而且在mac上試了一下,不行,只能在gun linux上玩。看了各個廠商在這方面的實現出入還很大!

結論
如果去掉test.c中strong的定義,就會報"重複定義"錯誤。

首先,從上面的例子可以看到,兩個模組共享變數。但是又和extern不同,extern就是宣告,完全沒有分配記憶體。但是這裡可是定義,照樣共享記憶體了!

例子1weak.c

void __attribute__((weak)) f();  

int main(void)

編譯

gcc weak.c結果

通過了,並且還能執行!很奇怪吧

例子2增加乙個f.c

#include void f(void)  

編譯

gcc weak.c f.c結果

hello from f

例子3修改weak.c

#include void __attribute__((weak)) f()  

int main(void)

編譯

gcc weak.c結果

hello from weak

編譯

gcc weak.c f.c結果

hello from f

注意

編譯方式不同,結果不同

結論根據上面三個例子,得到結論:

例1,只有弱符號f,編譯通過!沒有報reference f not defined!例2,3 f.c是強符號,結果執行結果用的是f.c中的f定義

最後乙個例子4

main.c

#include #include extern int fun(void);  

int global_var1 = 0xff00ff00; // 強符號

int main(int argc, const char *ar**)

test.c

#include #include #include double global_var1;  

int fun(void)

結論

C語言中的強符號與弱符號問題

弱符號與強符號 對於c c 語言來說,編譯器預設函式和初始化了的全域性變數為強符號,未初始化的全域性變數為弱符號。我們也可以通過gcc的 attribute weak 將乙個強符號變為弱符號。強符號和弱符號都是針對定義來說的,不是針對符號的引用。extern int ext int weak 弱符號...

C語言中的強符號和弱符號

c語言中的強符號和弱符號 c語言真的很奇怪,各種你想不到的問題都會出現,但是仔細分析這個問題,無不很有道理,這些都不是c語言的漏洞,而是這門語言的強大之處。首先介紹一下強符號和弱符號。當多個c檔案需要一起編譯執行的時候,就會有強弱符號的問題。為什麼會有多個c檔案一起編譯呢?這就的說起鏈結linkin...

C語言中的強符號和弱符號介紹

之前在extern c 用法詳解中已經提到過符號的概念,它是編譯器對變數和函式的一種標記,編譯器對c和c 在生產符號時規則也是不一樣的,符號除了本身名字的區別外,還有強符號和弱符號之分 我們先看一段簡單的 複製 如下 test.c void hello int main 很顯然,這段 是沒法鏈結通過...