((int []) {1,2,3})[0] = 100;
而且,我没有编译错误,并且可以猜测未命名数组的第一个元素已被修改为100。
因此,数组和复合字面量似乎是左值而不是常量值。
((int []) {1,2,3})[0] = 100;
而且,我没有编译错误,并且可以猜测未命名数组的第一个元素已被修改为100。
因此,数组和复合字面量似乎是左值而不是常量值。
这是一个左值,如果我们查看draft C99 standard第6.5.2.5
节Compound literals,它说(我强调的):
如果类型名称指定了一个未知大小的数组,则大小由初始化列表确定,如6.7.8所规定,复合字面量的类型为完成的数组类型。否则(当类型名称指定对象类型时),复合字面量的类型为类型名称指定的类型。在任一情况下,结果都是一个左值。
如果您想要一个const版本,在同一节中它给出了以下示例:
我们可以在这篇Dr Dobb的文章The New C: Compound Literals中找到术语的解释,它说:EXAMPLE 4 A read-only compound literal can be specified through constructions like:
(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}
int *p = (int []){1, 2, 3};
*p = 5; /* modified first element */
对于这样的复合字面量,也可以应用const
限定符,使元素为只读:
const int *p = (const int []){1, 2, 3};
*p = 5; /* wrong, violation of `const` qualifier */
*请注意,这并不意味着它自动成为可修改的左值(因此可以用作赋值运算符的左操作数),因为它具有数组类型,并参考C99草案6.3.2.1
Lvalues,arrays,and function designators:
可修改的左值是一个没有数组类型的左值,[...]
参考 C11 标准草案 N1570:
第 6.5.2.5 段第 4 段:
无论哪种情况,结果都是一个左值。
“左值”大致上是指指定对象的表达式——但需要注意并非所有左值都是可修改的。一个简单的例子:
const int x = 42;
x
是一个左值,但它不是可修改的左值。(数组类型的表达式不能是可修改的左值,因为你不能对数组对象进行赋值,但数组的元素可能是可修改的。)描述复合字面量的部分并没有明确说明未命名对象是否可修改。在缺乏这样的声明的情况下,该对象被认为是可修改的,除非类型被标记为复合字面量的值是由初始化列表初始化的未命名对象的值。如果复合字面量出现在函数体外部,则该对象具有静态存储期;否则,它具有与封闭块相关联的自动存储期。
const
。((int []) {1,2,3})[0] = 100;
这种语法并不是特别有用,因为在赋值之后没有办法引用未命名的对象。但是类似的结构可以非常有用。以下是一个人为制造的例子:
#include <stdio.h>
int main(void) {
int *ptr = (int[]){1, 2, 3};
ptr[0] = 100;
printf("%d %d %d\n", ptr[0], ptr[1], ptr[2]);
}
malloc
。6.3.2.1
可以得出结论,一个“可修改的左值”是指不具有数组类型的左值。因此,这样的复合字面量不是“可修改的左值”吗?我在我的答案中试图解释这一点,并假设这样的字面量在这方面实际上被视为数组类型。 - Grzegorz Szpetkowskiconst
限定,因此可以被修改。同样地,对于int arr[2] = { 10, 20 };
,名称arr
不是可修改的左值,但是定义创建的对象可以被修改。 - Keith Thompsontype* ptr = &(type){...}; *ptr = ...;
看起来像是一个可能的用例。我提出这个问题的原因是这里有一个类似的讨论: https://dev59.com/ZK3la4cB1Zd3GeqPTuF6。 - Lundin复合字面量是左值,其元素可修改。您可以为其分配值。甚至允许指向复合字面量的指针。
++
运算符。在数组的情况下,它是不可修改的。在CL的情况下,这没有任何意义。你所说的是可能的,标准关于CL的说法是它是可修改的。 - haccks
int
类型)和_浮点常量_。 - Grzegorz Szpetkowskiconst
)的概念是正交的。 - M.M