2013-12-10 50 views
9

我有下面的C代碼:在C中,爲什麼我初始化爲0的int變量被報告爲未初始化爲「nm」?

//declared at the beginning of the CAStar.c file: 
    int TERRAIN_PASSABLE = 1; 
    int TERRAIN_IMPASSABLE = 0; 
    int TERRAIN_SOME_WHAT_PASSABLE = 2; 

我注意到,對於這些變量,如果他們有一個非零值,它們被the "nm" command報道型「d」(初始化):

_TERRAIN_PASSABLE   |00000008| D | 
_TERRAIN_SOME_WHAT_PASSABLE|00000004| D | 

然而,這些初始化爲0被報告爲 「B」(未初始化):

_TERRAIN_IMPASSABLE  |00000000| B | 

爲什麼初始化之間的」差用0「和」用別的東西0初始化「?

+2

它可能是一種優化,其中編譯器不會將堆變量初始化爲零,因爲它期望OS從操作系統中清零內存......只是一個猜測雖然。 – ypnos

+0

@ypnos嗯,說實話,我也很喜歡這些線。但是,我留下了其中一個變量真正未初始化(只是:「int TERRAIN_SOME_WHAT_PASSABLE;」)。這個時間周圍的變量被報告爲「C」,所以(再次)與用0初始化(並且與用非0初始化時不一樣)不一樣。 –

+0

由於ld.so將所有內容初始化爲零。與您的應用程序的運行時內存分配(@ypnos)無關 - 僅表示運行時鏈接程序不必將變量設置爲任何特殊的值。 –

回答

5

這或多或少是關於BSS如何工作以及如何使用的。 B意味着變量將被放置在BSS部分(並且你是對的,它是未初始化的數據部分)。 D表示該符號位於初始化數據段中。

閱讀例如this的文章,瞭解更多關於BSS如何工作以及如何使用的文章。

+1

我認爲調用BSS未初始化是令人困惑的,因爲它確實是零初始化的。許多編譯器允許將數據放置到'.no_init'節或類似的地方,這是真正未初始化的。 – user694733

+0

謝謝,我現在明白了。它基本上是:「這裏是所有具有默認值的變量」列表,它不包含那些實際的默認值,以節省空間(對吧?) –

+0

@ user694733我在想同樣的事情,也許它應該被命名爲更具表現力,「未初始化」有點混亂。 –

4

很可能這些變量是在文件範圍內聲明的,給它們靜態存儲持續時間

爲了優化目的,所有具有靜態存儲持續時間的變量都由編譯器/鏈接器分爲兩類:初始化爲0或初始化爲其他內容。初始化爲零的變量放置在通常稱爲.bss的內存段中,而初始化爲其他值的變量則放置在.data中。

這樣做的原因是,如果在相鄰的存儲器中分配變量,則可以更快地初始化變量.bss。基本上他們將被初始化爲一個memset。此外,它會減少所需的ROM數量。 Releated question with details.

編輯

原因的.bss變量都在初始化的可能,因爲在C語言的規則(C11 6.7.9/10),指出這不是活得所有靜態存儲時間變量由程序員明確初始化(它們是「未初始化」),應初始化爲零