c - 为什么 C 中的复合文字是可修改的

标签 c c99 literals lvalue compound-literals

人们通常会将“不可修改”与字面量联系起来

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:

If the type name specifies an array of unknown size, the size is determined by the initializer list as specified in 6.7.9, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue.

可以看出,复合字面量的类型是一个完整的数组类型,并且是左值,因此与字符串字面量不同,它是可修改的

标准也提到了

§6.5.2.5/7:

String literals, and compound literals with const-qualified types, need not designate distinct objects.101

进一步说:

11 EXAMPLE 4 A read-only compound literal can be specified through constructions like:

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}   

12 EXAMPLE 5 The following three expressions have different meanings:

"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}

The first always has static storage duration and has type array of char, but need not be modifiable; the last two have automatic storage duration when they occur within the body of a function, and the first of these two is modifiable.

13 EXAMPLE 6 Like string literals, const-qualified compound literals can be placed into read-only memory and can even be shared. For example,

(const char []){"abc"} == "abc"

might yield 1 if the literals’ storage is shared.

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

相关文章:

c# - 尝试用文字 C# 替换 '

c - ISO C 标准定义了两类一致性实现

c - 如何将单个字符数字(如 '5')转换为整数

javascript - 如何检查对象中的对象是否存在

c - atexit 被认为是有害的?

c - 使用 C99 的 Netbeans C GCC

c - C语言中0是八进制还是十进制?

c++ - 用于导出和 C 和 C++ API 的单个头文件

c - 使用 wget 编程并将文件保存到内存中

c - 为什么有些 C 标准头文件以 'std' 开头,而有些则不是?