C 数组作为复合文字

C 数组作为复合文字,c,c99,compound-literals,C,C99,Compound Literals,在C99中,我们可以使用复合文字作为未命名数组 但是,这些文本是常数,例如100,'c',123.4f,等等 我注意到我可以做到: ((int []) {1,2,3})[0] = 100; 而且,我没有编译错误,可以猜测,未命名数组的第一个元素被修改为100 因此,似乎数组作为复合文字是左值而不是常量值。据我所知,你是对的,复合文字是左值*,你也可以取这样文字的指针(指向它的第一个元素): 也可以对这种复合文字应用const限定符,因此元素是只读的: const int *p = (const

在C99中,我们可以使用复合文字作为未命名数组

但是,这些文本是常数,例如
100
'c'
123.4f
,等等

我注意到我可以做到:

((int []) {1,2,3})[0] = 100;
而且,我没有编译错误,可以猜测,未命名数组的第一个元素被修改为100


因此,似乎数组作为复合文字是左值而不是常量值。

据我所知,你是对的,复合文字是左值*,你也可以取这样文字的指针(指向它的第一个元素):

也可以对这种复合文字应用
const
限定符,因此元素是只读的:

const int *p = (const int []){1, 2, 3};
*p = 5; /* wrong, violation of `const` qualifier */

*注意,这并不意味着它是可自动修改的左值(因此它可以用作赋值运算符的左操作数),因为它具有数组类型并参考C99草稿
6.3.2.1
左值、数组和函数指示符:

可修改的左值是没有数组类型[…]的左值


这是一个左值,如果我们看一下它所说的复合文字(强调我的话),我们可以看到这一点:

如果类型名称指定大小未知的数组,则大小为 由6.7.8中规定的初始值设定项列表和类型确定 复合文字的类型是完整数组类型的类型。否则 (当类型名称指定对象类型时),对象的类型 复合文字是由类型名称指定的文字在这两种情况下, 结果是一个左值。

如果您想要const版本,稍后在同一节中会给出以下示例:

示例4只读复合文字可以通过 结构如:

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}
我们可以在Dobb博士的文章中找到术语解释,并说:

复合文字不是真常量,因为 文字可能会改变,如后面所示。这让我们想到了一点 术语C99和C90标准[2,3]使用“常量”一词 对于表示真正不可更改的值的标记 无法在语言中修改。因此,10和3.14是一个整数 十进制常量和双精度浮点常量。 单词“literal”用于表示 可能不会如此恒定。例如,早期的C实现 允许修改引用字符串的值。C90和C99 禁止这种做法,说任何程序都不能修改字符串 文字有未定义的行为,这是标准的说法 它可能会工作,或者程序可能会以一种神秘的方式失败。[……]


复合文字是左值,其元素可以修改。你可以给它赋值。甚至可以使用指向复合文字的指针。

参考C11标准草案:

第6.5.2.5p4节:

无论哪种情况,结果都是左值

“左值”大体上是一个表示对象的表达式——但需要注意的是,并非所有左值都是可修改的。一个简单的例子:

const int x = 42;
名称
x
是一个左值,但它不是一个可修改的左值。(数组类型的表达式不能是可修改的左值,因为您不能指定给数组对象,但数组的元素可以修改。)

同一节第5段:

复合文字的值是未命名对象的值 由初始值设定项列表初始化。如果出现复合文字 在函数体之外,对象具有静态存储 期间否则,它将具有与关联的自动存储持续时间 封闭块


描述复合文字的部分没有明确说明未命名对象是否可修改。在没有此类语句的情况下,除非类型为
const
-qualified,否则对象将被视为可修改的

问题中的例子是:

((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]);
}
#包括
内部主(空){
int*ptr=(int[]){1,2,3};
ptr[0]=100;
printf(“%d%d%d\n”,ptr[0],ptr[1],ptr[2]);
}

如上所述,数组具有自动存储持续时间,这意味着如果它是在函数中创建的,那么当函数返回时,它将不再存在。复合文字不能替代malloc

那么,如果文字是常量,为什么会有文字命名?@xdevel2000:文字不是常量(例如,根据开关情况的要求);它们可能是只读值。更改只读值是未定义的行为:它可能在满月时工作…左值不一定意味着可修改的左值(正式的C标准术语)。只是对象在使用它的表达式之外仍然存在。只是要补充:我在标准(至少在C99 1256草稿中)中没有发现
100
'c'
123.4f
是任何形式的文字。它们分别被定义为整数常量、字符常量(也称为整数字符常量,强调
int
type)和浮动常量;在C99中,文字表示左值文字,常量表示右值文字。这与只读(即
const
)的概念是正交的。您的问题是什么?“描述复合文字的部分没有明确说明未命名对象是否可修改。”这样说是否正确(参考C99
6.3.2.1
)“可修改的左值是没有数组类型的左值”这类复合文字不是可修改的左值?我试图在回答中解释这一点,我假设在这方面,这些文字被有效地视为数组类型。@GrzegorzzPetkowski:数组的复合文字
#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]);
}