13 強符號和弱符號

2022-06-11 17:00:16 字數 2084 閱讀 2506

我們在編寫**的過程中經常會遇到一種叫做符號重複定義(multiple definition)的錯誤,這是因為在多個原始檔中定義了名字相同的全域性變數,並且都將它們初始化了。

例如,在 a.c 中定義了全域性變數 global:

int

global = 10;

在 b.c 中又對 global 進行了定義:

int

global = 20;

b.o: multiple definition of `global

'a.o: first defined here

這種符號的定義可以被稱為強符號。

在c語言中,編譯器預設函式和初始化了的全域性變數為強符號(strong symbol),未初始化的全域性變數為弱符號(weak symbol)。強符號之所以強,是因為它們擁有確切的資料,變數有值,函式有函式體;弱符號之所以弱,是因為它們還未被初始化,沒有確切的資料。

1)不允許強符號被多次定義,也即不同的目標檔案中不能有同名的強符號;如果有多個強符號,那麼鏈結器會報符號重複定義錯誤。

2)如果乙個符號在某個目標檔案中是強符號,在其他檔案中是弱符號,那麼選擇強符號。

3)如果乙個符號在所有的目標檔案中都是弱符號,那麼選擇其中占用空間最大的乙個。

比如目標檔案 a.o 定義全域性變數 global 為 int 型別,占用4個位元組,目標檔案 b.o 定義 global 為 double 型別,占用8個位元組,那麼被鏈結後,符號 global 占用8個位元組。請盡量不要使用多個不同型別的弱符號,否則有時候很難發現程式錯誤。

在 gcc 中,可以通過__attribute__((weak))來強制定義任何乙個符號為弱符號。假設現在有下面的一段**:

extern

intext;

intweak1;

int strong = 100

;__attribute__((weak)) weak2 = 2

;int

main()

weak1 和 weak2 是弱符號,strong 和 main 是強符號,而 ext 既非強符號也非弱符號,它是乙個對外部變數的引用(使用)。

為了加深理解,我們不妨再來看乙個多檔案程式設計的例子。

main.c 原始碼:

#include //

弱符號__attribute__((weak)) int a = 20

;__attribute__((weak))

void

func()

intmain()

module.c 原始碼:

#include //

強符號int a = 9999

;void

func()

在 gcc 中,使用下面的命令來執行程式:

$gcc main.c module.c

$./a.out

a = 9999

c.biancheng.net

在 main.c 中,a 和 func 都是弱符號,在 module.c 中,a 和 func 都是強符號,強符號會覆蓋弱符號,所以鏈結器最終會使用 module.c 中的符號,輸出結果也印證了這一點。

需要注意的是,__attribute__((weak))只對鏈結器有效,對編譯器不起作用,編譯器不區分強符號和弱符號,只要在乙個原始檔中定義兩個相同的符號,不管它們是強是弱,都會報「重複定義」錯誤。請看下面**:

#include __attribute__((weak)) 

int a = 20

;int a = 9999

;int

main()

這段**在編譯階段就會報錯,編譯器會認為變數 a 被定義了兩次,屬於重複定義。

弱符號對於庫來說十分有用,我們在開發庫時,可以將某些符號定義為弱符號,這樣就能夠被使用者定義的強符號覆蓋,從而使得程式可以使用自定義版本的函式,增加了很大的靈活性。

本文**:強符號和弱符號

強符號和弱符號

在c語言中,函式和初始化的全域性變數 包括顯示初始化為0 是強符號,未初始化的全域性變數是強符號。關於多個強弱符號定義型別不一致的主要有下面三種情況 1.兩個或兩個以上強符號型別不一致 2.有乙個強符號,其他都是弱符號 3.兩個或兩個以上弱符號型別不一致 對於情況一,編譯會報符號重定義錯誤。mapa...

C 強符號和弱符號

1 不允許強符號被多次定義,也即不同的目標檔案中不能有同名的強符號 如果有多個強符號,那麼鏈結器會報符號重複定義錯誤。2 如果乙個符號在某個目標檔案中是強符號,在其他檔案中是弱符號,那麼選擇強符號。3 如果乙個符號在所有的目標檔案中都是弱符號,那麼選擇其中占用空間最大的乙個。在 gcc 中,可以通過...

ARM 強符號與弱符號 強引用和弱引用

強符號與弱符號 可以通過使用 attribute weakref 這個擴充套件關鍵字來宣告對乙個外部函式的引用為弱引用 這種弱符號和弱引用對於庫來說十分有用,比如庫中定義的弱符號可以被使用者定義的強符號所覆蓋,從而使得程式可以使用自定義版本的庫函式 或者程式可以對某些擴充套件功能模組的引用定義為弱引...