2016-10-02 24 views
2

拆卸下面的代碼後:爲什麼向主函數聲明的本地字符串是Rodata段存儲器的一部分?

#include <stdio.h> 

static const char HELLO1[] = "Howdy"; 

int main(){ 
char hello2[6]="hello\0"; 
printf("%s",string); 
} 

我可以看到字符串HELLO1被宣佈爲.RODATA段常數變量聲明爲這部分是可以理解的。

但是,hello2也被聲明爲.RODATA段。但是局部變量被聲明爲Stack直接對嗎?

你能解釋一下爲什麼這個字符串被聲明爲這個段嗎?

+1

答案取決於使用的編譯器/平臺 - 哪兩個都沒有。 – chux

+1

公爵,你使用的編譯標誌是什麼?然而,下面的@NulledPointer註釋並沒有在堆棧中創建'hello2';他們可能已經發射了一個堆疊的弦。我注意到'clang'也會對聚合數據類型做到這一點。 –

回答

1

C程序中經常使用memcpy和memset內部建立堆棧的內容在運行時。雖然這是與平臺相關的,它是常見的代碼像您一樣擴展到類似:

#include <stdio.h> 

static const char HELLO1[] = "Howdy"; 

int main(){ 
    // hidden 
    static const char *__temporary_main_hello2 = "hello\0"; 
    char hello2[6]; 
    // hidden 
    memcpy(hello2, __temporary_main_hello2, sizeof(hello2)); 
    printf("%s",string); 
} 

現在你可以看到爲什麼打招呼也是.RODATA。該字符串的原始數據來自.rodata中的靜態數據,但數組hello2的存儲位於堆棧中。當調用main時,編譯器需要一種方法來填充hello2。如果平臺有一種方便的方式來在立即數中表示數據,那麼可以這樣做,但爲此使用經過優化的memcpy通常更方便。

+1

x86上初始化程序數據更常見於指令流中的立即數,而不是從靜態數據中複製。看到我對其他答案的評論。但是,也許OP正在爲ARM編譯? (至少需要三條指令才能將32位文字數據存儲到內存中。)Godbolt也有ARM編譯器:實際上初始化器是從'.LC0'複製的(在花費兩條指令獲取.LC0的地址之後一個寄存器)。 https://godbolt.org/g/b7RbW0 –

+0

對不起,我遲到的評論。我爲x86使用GCC。你能否說出爲什麼你的答案和NulledPointer不一樣?您的回答是GCC靜態存儲實現的解釋(通過使用memcpy在運行時構建堆棧的內容)? –

+0

兩個答案都得出了相同的結論,但我認爲通過一個具體的例子可以更容易地看到實際發生的情況。 –

3

String literals存在該程序

字符串文字具有static storage duration的壽命,並且因此在存儲器 存在用於程序的壽命。

Static storage duration

對象的存儲空間在程序開始時分配,並且 在程序結束時解除分配。只存在對象 的一個實例。在命名空間範圍(包括全局 名稱空間)聲明的所有對象都具有此存儲持續時間,以及使用靜態 或extern聲明的那些存儲持續時間。

所以gccELF二進制

,進一步擬訂...

char a[] = "Hello world A"; 
char* p = "Hello world P"; 

對於這兩種ap,他們的字符串文字具有靜態存儲時間(這意味着他們實現.RODATAstatic storage兩者都存儲在.RODATA中),區別在於對於a,字符串文字被複制到此堆棧變量中,而p只是指向.RODATA內存。這就是爲什麼你可以修改a但不p

注意:要知道,上述文獻是從c++語法,但對於c的原因是相同的

+0

這是很好的答案,然而'char hello2 [6] =「hello \ 0」;'不構成'「hello \ 0」'爲_string literal_。 ''hello \ 0''初始化器用作'{'h','e','l','l','o','\ 0'}'_array initializer_的同構糖。 –

+0

@GrzegorzSzpetkowski爲您的困惑更新了答案。 – PnotNP

+0

C11 6.7.9/p14:'一個字符類型的數組可以用一個**字符串文字**或UTF-8字符串 文字初始化,可以用大括號括起來。我還檢查了'char hello2 [6] =「hel」「lo \ 0」;',這是有效的構造並證明了你的觀點。 –

相關問題