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