簡體   English   中英

復合字符 arrays 和字符串文字之間是否存在任何內部差異?

[英]Are there any internal differences between compound char arrays and string literals?

這之間是否有任何內部差異:

(const char[]){'H', 'e', 'l', 'l', 'o', 0}

"Hello"

在 C 中?
我注意到用引號聲明的字符串文字是由strings unix 命令獲得的,但其他的不是。 導致這種情況的內部差異是什么?

字符串文字始終具有 static 存儲持續時間,而塊 scope 的復合文字具有自動存儲持續時間。

字符串文字在初始化程序中具有特殊狀態,例如

char x[5] = "foo";  // ok
char y[5] = (char[]){'f','o','o','\0'};   // error

字符串字面量不一定有唯一的地址,例如"foo" == "foo"可能是也可能不是真的,而"foo" + 1 == "oo"可能是也可能不是真的,而復合字面量的類似比較必須是假的。

這可能是因為strings命令在 object 文件中查找字符串文字,並且當您使用char *str="Hello"聲明字符串時,編譯器將其保存為字符串文字並標記它。 GCC 使用.string關鍵字顯示此 memory 位置,而 clang 使用.asciz

另一方面,當您將字符串聲明為字符數組時,它們將作為連續字節存儲在 memory 中,並且不使用.string或 '.asciz' 標記

拿這個簡單的 function

int test() {
    (const char[]){'H', 'e', 'l', 'l', 'o', 0};
    char *str="Hello";
}

下面是 GCC 生成的代碼(沒有任何代碼優化)。 clang 給出了類似的代碼,但是來自 GCC 的代碼更簡單,所以為了簡單起見,我使用它

.LC0:
        .string "Hello"
test:
      push    rbp                                 ; function prologue
      mov     rbp, rsp                            ; function prologue
      mov     BYTE PTR [rbp-14], 72               ; ASCII H
      mov     BYTE PTR [rbp-13], 101              ; ASCII e
      mov     BYTE PTR [rbp-12], 108              ; ASCII l
      mov     BYTE PTR [rbp-11], 108              ; ASCII l
      mov     BYTE PTR [rbp-10], 111              ; ASCII o
      mov     BYTE PTR [rbp-9], 0                 ; ASCII null 
      mov     QWORD PTR [rbp-8], OFFSET FLAT:.LC0 ; string literal
      nop
      pop     rbp
      ret

function prologue之后,字節被一個一個移動到 memory 但不標記為字符串。 而你的char *str="Hello"; 用 label 標記,我假設strings實用程序只是搜索這些文字。

字符串文字通常存儲在 memory 的只讀部分中,而復合文字 char arrays 則不是。

例如,給定以下代碼:

char *x = (char *)(const char[]){'H', 'e', 'l', 'l', 'o', 0};
char *y = "Hello";
x[0] = 'X';
printf("x=%s\n", x);
y[0] = 'X';
printf("y=%s\n", y);

x[0]的修改成功並打印修改后的字符串,而對y[0]的嘗試更改會導致段錯誤。

暫無
暫無

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

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