C/C++關於全域性變數和區域性變數初始化與不初始化的區別
在C語言裡,全域性變數如果不初始化的話,預設為0,也就是說在全域性空間裡:int x =0; 跟 int x; 的效果看起來是一樣的。但其實這裡面的差別很大,強烈建議大家所有的全域性變數都要初始化,他們的主要差別如下:
編譯器在編譯的時候針對這兩種情況會產生兩種符號放在目標檔案的符號表中,對於初始化的,叫強符號,未初始化的,叫弱符號。聯結器在連線目標檔案的時候,如果遇到兩個重名符號,會有以下處理規則:
1、如果有多個重名的強符號,則報錯。
2、如果有一個強符號,多個弱符號,則以強符號為準。
3、如果沒有強符號,但有多個重名的弱符號,則任選一個弱符號。
大部分情況下,我們不希望聯結器為我們做決定,所以我不是很認同後兩個規則,至少應該給個警告,
注: bss段(未手動初始化的資料)並不給該段的資料分配空間,只是記錄資料所需空間的大小。
data段(已手動初始化的資料)則為資料分配空間,資料儲存在目標檔案中。
對於區域性變數,不被初始化的話,其值一般分為兩種情況Debug版和Release版的區別。
例:
#include "stdafx.h"
int i;
int main(int argc, char* argv[])
{
printf(" i = %d\n",i);
int j;
printf(" j= %d\n",j);
return 0;
}
在Debug版下,在這段程式碼中i的值打印出來是0,而j的值打印出來是-858993460,也就是0xCCCCCCCC.至於為什麼是這個值,有網友給出這個解釋。(設計成0xcccccccc是有特殊用意的……這個好像叫做Poison,未初始化的Pointer去取值的話會出錯。肯定有人問為什麼不弄成0x00000000,因為空指標是指針的有效狀態,可能會誤導人,而0xCCCCCCCC在Windows下永遠不可能是一個指標的有效狀態(不是NULL,不指向一個物件,不指向一堆物件緊接之後的區域),這就是在模擬野指標……)。
值得注意的是,同樣的程式碼在Release版下,這段程式碼中未被初始化的變數最後打印出來的可能都是0。
鑑於上面分析,建議大家養成初始化一個變數的習慣。