全局變量存儲位置取決於初始化方式:
關鍵差異:COMMON 段屬於弱符號,BSS 段(顯式初始化 0)屬於強符號。
// test1.c
int init = 0; // 強符號,放入 BSS 段
// test2.c
int init = 1; // 強符號,放入 DATA 段
鏈接報錯:multiple definition of 'init'
// test1.c
int init; // 未初始化,弱符號,放入 COMMON 段
// test2.c
int init = 1; // 強符號
鏈接成功,但運行時 init1() 讀到的值為 1(被 test2 覆蓋),而非預期的 0,導致邏輯錯誤且無任何警告。
| 屬性 | BSS 段(顯式初始化 0) | COMMON 段(未初始化) |
|---|---|---|
| 符號類型 | 強符號 | 弱符號 |
| 同名符號鏈接 | 報錯 | 弱符號被強符號覆蓋 |
| 運行時初始值 | 保證為 0 | 可能被其他文件同名強符號修改 |
使用 -fno-common 強制將未初始化全局變量放入 BSS 段(強符號):
gcc -fno-common -c test1.c
gcc -fno-common -c test2.c
gcc -o test main.c test1.o test2.o // 現在會報 multiple definition 錯誤
static,限制作用域,避免符號衝突module_var)-fno-common 和 -Wall 進行編譯檢查BSS 與 COMMON 的區別不在於運行時值(均為 0),而在於鏈接階段的符號解析規則。理解這一機制對編寫健壯、可維護的多文件 C 專案至關重要。