繁体   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