2010-10-17 23 views
5
#include <stdio.h> 

const int str[1000] = {0}; 

int main(void) 
{ 
    printf("arr is %d\n", str[0]); 
    return 0; 
} 

具有以下的輸出:聲明爲「const」的全局初始化變量轉到文本段,而聲明爲「Static」的全局變量轉到數據段。爲什麼?

[-exercises/adam/stack2]:size a.out 
    text data  bss  dec  hex filename 
    5133  272  24 5429 1535 a.out 

鑑於:

#include <stdio.h> 

static int str[1000] = {0}; 

int main(void) 
{ 
    printf("arr is %d\n", str[0]); 
    return 0; 
} 

具有以下的輸出:

[-exercises/adam/stack2]:size a.out 
    text data  bss  dec  hex filename 
    1080 4292  24 5396 1514 a.out 

當陣列未初始化 - 它再次進入文本段爲「const」,BSS爲「靜態」。

該變量是全局變量,應該可以從它所屬的可執行文件中的任何地方訪問(因爲沒有「靜態」),但給定了變量,我不知道它爲什麼放在文本段而不是數據中分割?

+0

+1:好問題。你可能想把它擴展到'static const'。 – Arun 2010-10-17 17:49:27

回答

6

你很困惑。在conststatic之間沒有二分法;這兩個是獨立的。假設所有數據都已初始化,則static const和外部(全局)const將進入text,並且非const合格的static和非const合格的外部將進入data

至於bss,像ELF這樣的現代二進制格式對於恆定和非恆定的零數據實際上有單獨的bsssize命令的輸出只是不顯示它。

+0

你說得對。感謝您的澄清。 – helpmelearn 2010-10-17 18:25:42

3

允許內存保護工作。任何嘗試寫入常量都會觸發段錯誤。

1

當你聲明一個變量const時,你告訴編譯器你永遠不打算改變它的值。另一方面,通過在文件範圍聲明static,您告訴編譯器該變量對於已聲明的編譯單元是私有的,但該編譯單元中的函數仍允許修改此變量。

由於Oli在他的answer中提到,在text段中定位const變量允許系統強制執行內存訪問保護。另外,考慮一個嵌入式系統,在這種情況下,text段通常寫入閃存,因此是不可修改的。 databss段等位於RAM中,並且允許其修改。

7

Kernighan的&裏奇

靜是一個存儲類說明。 其他存儲類別說明符是: auto,register,extern & typedef。靜態指定符爲 對象提供靜態存儲類。應用於外部變量或函數的靜態聲明將該對象的範圍限制爲正在編譯的源文件的其餘部分。靜態 對象可能位於所有塊外部的塊或 ,但在 大小寫保留其值從整個出口 開始並重新進入功能塊和 塊。

然而,

const爲類型限定符。其他 類型限定符是易失性的。 const的目的是宣佈 可能被放置在 只讀內存中的對象,也許 增加優化 的機會。

我想可以推斷出這兩個關鍵字有不同的目的; const的變量在text/code segment中的變量與其目的相當明顯。

+2

+1用於引用K&R – 2010-10-17 18:06:12

1

通過將常量數據放入文本部分,編譯器試圖強制執行常量。

請記住,TEXT部分已加載到標記爲只讀在MMU頁表中的內存頁中。這是爲了防止代碼的意外損壞。通過將常量數據放入同一區域,使該數據只讀。對這些數據的任何寫入都會調用異常。

聲明爲靜態的未初始化數據將進入BSS段以節省可執行文件中的空間。該區域由加載程序分配在內存中。聲明爲靜態的初始化數據將進入讀寫的DATA段。