【问题标题】:Assignment of array elements in array initialization [duplicate]数组初始化中数组元素的赋值[重复]
【发布时间】:2019-02-17 20:07:25
【问题描述】:

考虑以下简单程序:

#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;

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

这是否有效且定义明确?它可以是实现定义的、未定义的还是未指定的?


这个问题与问题Confusion about Array initialization in C有关。

【问题讨论】:

  • 是的,这似乎与另一个问题非常相似,但只是处理另一个方面。我不完全确定是否重复但对另一个问题的一个好的答案可以涵盖这个主题。有趣的是,这个问题的投票率远高于另一个问题,这可能是另一个指标,表明投票更有可能给予高代表用户。这绝不是评论家@OP,但我觉得这很有趣。
  • 让我们问真正的问题!为什么int a[5] = { a[2] = 1, a[3] =2 }; 给我们1 2 0 0 0?!
  • 我看不出这与其他问题有何不同。您基本上回答了另一个问题,说“我真的不知道这里发生了什么”,并发布了同一问题的另一个副本。对这个问题的任何实际有用的答案都会回答另一个问题,反之亦然
  • 我已经发布了另一个问题的语言律师回答。

标签: c initialization language-lawyer


【解决方案1】:

虽然我不能说我是一名 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)分配给@ 的第一个元素987654332@。其他 in 索引保留为 0,因此模式 1 0 1 0 0 被打印出来。

【讨论】:

  • 问题是标准说了什么,而不是编译器做了什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 2012-02-08
  • 2015-01-28
相关资源
最近更新 更多