这个问题在这里已有答案:
考虑以下简单程序:
#include <stdio.h>
int main(void)
{
int a[5] = { a[2] = 1 };
printf("%d %d %d %d %d\n", a[0], a[1],a[2], a[3], a[4]);
}
使用GCC 7.3.0输出
1 0 1 0 0
考虑到a[1]
为零,似乎初始化类似于
int a[5] = { 1 };
a[2] = 1;
问题是:虽然初始化器可以是任何通用表达式,但是初始化和分配的顺序是什么?
这甚至是有效且定义明确的吗?可能是实现定义,未定义或未指定?
虽然我不能说,我是ISO专家,这是我在godbolt的帮助下发现的。
首先,我在-fsanitize=undefined
的帮助下构建了样本,这很好地表明了未定义的行为。海湾合作委员会和铿锵声都没有抱怨。
接下来我看了gcc执行的各个阶段,在这种情况下是gimple
阶段
foo ()
{
int a[5];
try
{
# DEBUG BEGIN_STMT
a = {};
a[2] = 1;
_1 = a[2];
a[0] = _1;
# DEBUG BEGIN_STMT
_2 = a[4];
_3 = a[3];
_4 = a[2];
_5 = a[1];
_6 = a[0];
printf ("%d %d %d %d %d\n", _6, _5, _4, _3, _2);
}
finally
{
a = {CLOBBER};
}
}
在这里你可以看到,首先定义了数组a
,然后将1
分配给a[2]
,然后将结果(1
,因为it is an assignment)分配给a
的第一个元素。索引中的另一个保留为0,因此打印出模式1 0 1 0 0
。