c語言中的強符號和弱符號
c語言真的很奇怪,各種你想不到的問題都會出現,但是仔細分析這個問題,無不很有道理,這些都不是c語言的漏洞,而是這門語言的強大之處。
首先介紹一下強符號和弱符號。
當多個c檔案需要一起編譯執行的時候,就會有強弱符號的問題。為什麼會有多個c檔案一起編譯呢?這就的說起鏈結linking,關於linking你可以去看這個。
在一起編譯的c檔案中,如果存在多個變數名相同的全域性變數(global,一定是全域性的,並且不能是static的),如果他們都沒有初始化,那麼他們就是虛符號。如果有乙個初始化了,那麼他就是強符號,其他的就是虛符號。如果存在多個初始化的變數,那麼就會報錯。對於第一種情況,系統會有某種機制選取乙個作為整個的全域性變數,這種機制說明了,它會按照一種順序選取,而不是隨機選取。這種順序可能是編譯時候的檔案順序,也可能是別的。第二種情況就比較可愛了。直接使用強符號作為全域性變數。第三種是不允許的。
好了下面進行測試:
編譯方法:
gcc –o testa.c b.c
執行方法:
./test
對於第一種情況,編寫**如下:
第乙個檔案:
$ vim a.c
#includeint x=1234,y=1234;
int main()
第二個檔案:
$vim b.c
double x;
void f()
這個測試程式的目的很簡單,就是兩個c檔案中出現了相同的變數x,在a.c中進行了初始化,因此在a.c中就是強符號,在記憶體中就占用4個位元組,同樣y也占用4個位元組。但是在b.c中,f()函式將-0.0賦值給x,這可是乙個double啊。於是就將y占用的4個位元組也給占領了。
測試結果:
x = -1431655949,address is 601040
y = -1060641622,address is 601044
簡單分析一下:
從位址可以看出,x占用了4個位元組,呼叫f()函式後,將double賦值給x,就把y也給汙染了。列印出來的資料不再分析,這涉及到浮點數在記憶體中的儲存方式。
換測試程式如下:
第乙個檔案:
$vim a.c
#includeint x,y;
int main()
第二個檔案:
$vim b.c
double x = -0.0;
f()
這樣在b.c中的x就成了強符號,那麼記憶體分配時,就會給他8個位元組。
測試結果如下:
x = 0, address is 601048
y = 0, address is 601050
這,讓我始料未及啊,怎麼就成2個位元組了呢。呵呵,我承認我是個渣貨,突然明白,這是16進製制!!!48到50就是8個位元組有48 49 4a 4b 4c 4d 4e 4f。
再換測試程式如下:
第乙個檔案:
$vim a.c
#includeint x,y;
int main()
第二個檔案:
$vim b.c
double x;
f()
測試結果如下:
x = 0, address is601048
y = 0, address is601050
意味著編譯器選擇了double型的分配了記憶體,我懷疑是編譯順序的問題,但是調換為
gcc –o test b.c a.c
結果還是這樣。
好了,總結一下。
當多個檔案一起編譯時,全域性變數就變得很危險,非常危險。你可以有下面幾種解決方案:
1、上策:想辦法消除全域性變數。全域性變數會增加程式的耦合性,對他要控制使用。如果能用其他的方法代替最好。
2、中策:實在沒有辦法,那就把全域性變數定義為static,它是沒有強弱之分的。而且不會和其他的全域性符號產生衝突。至於其他檔案可能對他的訪問,可以封裝成函式。把乙個模組的資料封裝起來是乙個好的實踐。
3、下策:把所有的符號全部都變成強符號。所有的全域性變數都初始化,記住,是所有的,哪怕初始值是0都行。如果乙個沒有初始化,就可能會和其他人產生衝突,儘管別人初始化了。(自己寫**測試一下)。
4、必備之策:gcc提供了乙個選項,可以檢查這類錯誤:-fno-common。
如果你覺得這很低端,你可以去這。他寫的很高階。
C語言中的強符號和弱符號介紹
之前在extern c 用法詳解中已經提到過符號的概念,它是編譯器對變數和函式的一種標記,編譯器對c和c 在生產符號時規則也是不一樣的,符號除了本身名字的區別外,還有強符號和弱符號之分 我們先看一段簡單的 複製 如下 test.c void hello int main 很顯然,這段 是沒法鏈結通過...
C語言中的強符號與弱符號
參考 程式設計師的自我修養 參考 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...
關於C語言中的強符號 弱符號 強引用和弱引用
首先我表示很悲劇,在看 程式設計師的自我修養 鏈結 裝載與庫 之前我竟不知道c有強符號 弱符號 強引用和弱引用。在看到3.5.5節弱符號和強符號時,我感覺有些困惑,所以寫下此篇,希望能和同樣感覺的朋友交流也希望高人指點。首先我們看一下書中關於它們的定義。引入場景 1 檔案a中定義並初始化變數i in...