c 中區域性變數初始化的問題

2021-09-08 20:11:52 字數 1642 閱讀 2363

在c語言裡,全域性變數如果不初始化的話,預設為0,也就是說在全域性空間裡:

編譯器在編譯的時候針對這兩種情況會產生兩種符號放在目標檔案的符號表中,對於初始化的,叫強

符號,未初始化的,叫弱符號。聯結器在連線目標檔案的時候,如果遇到兩個重名符號,會有以下處理規

則:1、如果有多個重名的強符號,則報錯。

2、如果有乙個強符號,多個弱符號,則以強符號為準。

3、如果沒有強符號,但有多個重名的弱符號,則任選乙個弱符號。

大部分情況下,我們不希望聯結器為我們做決定,所以我不是很認同後兩個規則,至少應該給個警告,

而不應該安靜地通過。因為這種問題引起的bug會很難查,所以我們要盡量把全域性變數初始化,對於不想給

別的檔案引用的變數,也盡量用static修飾。

除了連線時的表現不一樣外,未初始化的符號在目標檔案的bss段中,而初始化的符號在data段中。

注: bss段(未手動初始化的資料)並不給該段的資料分配空間,只是記錄資料所需空間的大小。

data段(已手動初始化的資料)則為資料分配空間,資料儲存在目標檔案中。

對於區域性變數,不被初始化的話,其值一般分為兩種情況debug版和release版的區別。

例:#include "stdafx.h"

int i;

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

在debug版下,在這段**中i的值列印出來是0,而j的值列印出來是-858993460,也就是0xcccccccc.

至於為什麼是這個值,有網友給出這個解釋。(設計成0xcccccccc是有特殊用意的……這個好像叫做

poison,未初始化的pointer去取值的話會出錯。肯定有人問為什麼不弄成0x00000000,因為空指標是指

針的有效狀態,可能會誤導人,而0xcccccccc在windows下永遠不可能是乙個指標的有效狀態(不是null,

不指向乙個物件,不指向一堆物件緊接之後的區域),這就是在模擬野指標……)

值得注意的是,同樣的**在release版下,這段**中未被初始化的變數最後列印出來的可能都是0。

也有強大的網友給出解釋。(重點在於vc的乙個功能:catch release-build errors in debug build用

/gz編譯開關開啟。debug版這個開關是開的,release版是關的(為了效率)。這個開關說白了就是把所有

動態區域性變數初始化成0xcccccccc,把所有動態堆變數初始化成0xcdcdcdcd。很多新手會忘記初始化這些

本來應該初始化的變數(尤其是new出來的變數),有時他們會假定這些變數應該是0,這樣就可能出現在

release版正常而debug版不正常的程式,因為release版至少區域性變數的初始值很可能就是0,而有時他們

又會假定或者期望這些變數不是0,這樣就帶了乙個最難發現的bug)

from:

不過個人去驗證區域性變數,沒初始化,訪問會直接編譯不過。

相比類裡的成員物件沒初始化變數的值也分物件構建的方式而不同:

struct npc

;npc* pnpc = new npc; // new npc()

printf("m default value = %d\n", pnpc->m);

npc()會呼叫預設建構函式,會對成員變數初始化0,new npc則不會,data的值會是不確定的。

golang基礎 區域性變數初始化

操作 只能用於方法內部,宣告並初始化新的變數 v 3 但是不能用於已宣告變數賦值,下面的做法編譯器會報錯誤 no new variables on left side of var v int 0 v 1 通過錯誤可以了解到,操作左邊必須要有新變數,那麼多個變數初始化只需要滿足左邊至少有乙個新變數即...

區域性變數和全域性變數的初始化

寫 的時候遇到了這個問題,選兩段抄過來做個筆記。定義區域性變數,其實就是在棧中通過移動棧指標來給程式提供乙個記憶體空間和這個區域性變數名繫結。因為這段記憶體空間在棧上,而棧記憶體是反覆使用的 髒的,上次用完沒清零的 所以說使用棧來實現的區域性變數定義時如果不顯式初始化,值就是髒的。在c語言裡,全域性...

區域性變數和成員變數初始化的不同

1.區別 值型別的 區域性變數必須初始化,成員變數宣告時預設初始化。也就是說,區域性變數使用前,必須賦值。而成員變數 會預設賦值,不必須。2.預設值是什麼?成員變數中里的,基本數值型別預設初始值為0,string等非基本型別初始化為null。why?值型別在棧中,值在是在棧中。而string等引用型...