考虑以下简单程序:
#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
Considering that a[1]
is zero, it seems that the initialization is similar to
int a[5] = { 1 };
a[2] = 1;
问题是:虽然初始化器可以是任何泛型表达式,但初始化和赋值的顺序是什么?
这是否有效且定义明确?它可以是实现定义的、未定义的还是未指定的?
这个问题与问题Confusion about Array initialization in C相关.
虽然我不能说我是 ISO 专家,但这是我在 godbolt 的帮助下发现的.
首先,我在 -fsanitize=undefined
的帮助下构建了示例,这很好地表明了未定义的行为。 GCC 和 clang 都没有提示。
接下来我查看了 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
。