[英]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.