簡體   English   中英

char數組和指針初始化語義

[英]char array and pointer initialization semantics

在以下代碼段中

   char *str1 = "abcd";
   char str2[] = "defg";

我意識到,第一條語句將指向字符串文字的指針存儲在可執行文件的只讀部分中,而第二條語句將指針存儲到讀寫部分中。 檢查生成的指令后,我確認第一個指令在str1的rodata節中存儲了指向“ abcd”的指針。

有趣的是第二個陳述。 編譯器插入代碼以將值存儲到

char *str1 = "abcd";
8048420:       c7 44 24 10 20 85 04    movl   $0x8048520,0x10(%esp)
8048427:       08
char str2[] = "defg";
8048428:       c7 44 24 17 64 65 66    movl   $0x67666564,0x17(%esp)
804842f:       67
8048430:       c6 44 24 1b 00          movb   $0x0,0x1b(%esp)

編譯器如何決定何時執行以下操作?

  1. 字符串文字存儲在rodata節中
  2. 字符串文字存儲在數據節(rw)中
  3. 字符串存儲器在堆棧中是隱式的,並且生成指令來填充堆棧嗎?
  4. 是否還有其他可能性以及硬件之間的差異?

注意:我正在運行帶有調試符號和-O0的Precision32 vagrant,gcc

當使用編譯時聚合值(不限於字符串文字)初始化內存中的聚合對象時,編譯器始終可以選擇

  1. 在編譯時在只讀數據部分中預先構建完整的初始化程序,然后在運行時使用memcpy將整個事情復制到可修改的目標值中。

  2. 生成將在運行時逐段直接構建目標值的代碼。

基本上,第一種是“基於數據”的方法,第二種是“基於代碼的”方法。 在您的情況下,編譯器使用基於代碼的解決方案,可能是因為文字簡短。 使用更長的文字,我懷疑它將最終切換到第一種方法。

一個可能會想到,在某些情況下,混合方法可能被一些編譯器使用:部分數據是預編譯的地方,並memcpy -ed分從那里,數據的其余部分是建立在飛。

如果你的

char str2[] = "defg";

定義位於函數內部,然后編譯器將生成指令以將數據放入堆棧(忽略可能的優化,例如,將值僅保留在寄存器中)。 就像其他自動(堆棧)變量一樣。

它也可以選擇將數據從其他地方復制到堆棧,而不是例如將數據值作為指令的立即操作數。 它可能選擇對更長的字符串執行此操作,以避免代碼膨脹。

無論編譯器做什么,都不能在下一次調用該函數時看到對str2內容的修改(就像其他自動變量一樣)。

如果str2是全局的(為其提供了靜態存儲持續時間),則數據將最終位於讀/寫數據段中。 如果您在函數中為數組提供靜態存儲持續時間,也會發生這種情況,如下所示:

static char str2[] = "defg";

用字符串文字初始化指針時,如

char *s = "defg";

,數據以只讀數據段結尾,並且如何使用數據的地址初始化指針本身的規則與上述相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM