在数组初始化中分配数组元素

Som*_*ude 6 c initialization language-lawyer

考虑以下简单程序:

#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]);
}
Run Code Online (Sandbox Code Playgroud)

使用GCC 7.3.0输出

1 0 1 0 0

考虑到这a[1]是零,似乎初始化类似于

int a[5] = { 1 };
a[2] = 1;
Run Code Online (Sandbox Code Playgroud)

问题是:虽然初始化器可以是任何通用表达式,但是初始化和分配的顺序是什么?

这甚至是有效且定义明确的吗?可能是实现定义,未定义或未指定?


这个问题与C中关于数组初始化的混淆问题有关.

hel*_*low 0

虽然我不能说我是 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};
    }
}
Run Code Online (Sandbox Code Playgroud)

a在这里您可以看到,首先定义了数组,然后1将其分配给a[2],然后将结果(1,因为它是赋值)分配给 的第一个元素a。索引中的其他值保留为 0,因此1 0 1 0 0打印出图案。

  • 问题是标准怎么说,而不是编译器做什么 (4认同)