人们通常会将“不可修改”与术语literal关联起来。

char* str = "Hello World!";
*str = 'B';  // Bus Error!

但是,当使用复合文字时,我很快发现它们是完全可修改的(并且锁定生成的机器代码,您会看到它们被推到堆栈上):
char* str = (char[]){"Hello World"};
*str = 'B';  // A-Okay!

我正在用clang-703.0.29编译。这两个例子不应该产生完全相同的机器代码吗?复合文字真的是文字吗,如果可以修改的话?
编辑:一个更简短的例子是:
"Hello World"[0] = 'B';  // Bus Error!
(char[]){"Hello World"}[0] = 'B';  // Okay!

最佳答案

复合文字是左值,其元素的值是可修改的。万一

char* str = (char[]){"Hello World"};
*str = 'B';  // A-Okay!

您正在修改合法的复合文字。
C11-§6.5.2.5/4:
如果类型名指定了未知大小的数组,则大小由6.7.9中指定的初始值设定项列表确定,并且复合文本的类型是已完成数组类型的类型。否则(当类型名指定对象类型时),类型
复合文字的是由类型名指定的文字。无论哪种情况,结果都是左值。
可以看出,复合文本的类型是一个完整的数组类型,并且是左值,因此它不像字符串文本那样是可修改的。
标准也提到
第6.5.2.5/7条:
字符串文本和具有常量限定类型的复合文本不需要指定不同的对象。101
进一步说:
11示例4只读复合文本可以通过如下结构指定:
(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}

12例5以下三个表达式有不同的含义:
"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}

第一个始终具有静态存储持续时间,类型数组为char,但不需要修改;最后两个在函数体中出现时具有自动存储持续时间,其中第一个
二是可修改的。
13例6与字符串文本类似,常量限定的复合文本可以放入只读内存,甚至可以共享。例如,
(const char []){"abc"} == "abc"

如果共享文本的存储,则可能产生1。

关于c - 为什么C中的复合文字可以修改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36676149/

10-11 21:19