i = x[i]++ 吗?导致未定义的行为?

Pav*_*kin 5 c arrays undefined-behavior language-lawyer post-increment

有人可以解释一下是否i = x[i]++;会导致未定义的行为吗?

\n

注意:x[i]i并不都是易失性的且不x[i]重叠i

\n

有 C11,6.5 表达式,2(添加强调):

\n
\n

如果标量对象上的副作用相对于同一标量对象的不同副作用使用同一标量对象的值的值计算而言是无序的,则该行为是未定义的。如果表达式的子表达式有多个允许的\n排序,并且在任何排序中出现这种未排序的副作用,则行为是未定义的。84)

\n
\n

我认为:

\n
    \n
  • 不存在“同一标量对象上的不同副作用”
  • \n
  • 不存在“使用同一标量对象的值进行值计算”
  • \n
\n

是否有“多重允许的订购”?

\n

总体而言:如何i = x[i]++;解释序列点、副作用和未定义的行为(如果有)?

\n
\n

UPD。结论:会i = x[i]++;导致 2 个副作用:

\n
    \n
  1. “操作数对象的值递增”(后缀递增)
  2. \n
  3. “更新左操作数的存储值”(赋值运算符)
  4. \n
\n

该标准没有定义副作用发生的顺序。

\n

因此,根据 C11,4. 一致性,2:

\n
\n

未定义的行为在本国际标准中另外通过文字 \xe2\x80\x98\xe2\x80\x98undefinedbehavior\xe2\x80\x99\xe2\x80\x99 或通过省略任何明确的行为定义来表示。

\n
\n

实验表明,GCC/LLVM/ICC 有序1-2,而 MSVC(和其他一些)有序2-1

\n
\n

额外(推测):为什么不使其成为未指定的行为?示例:“未指定行为的一个示例是副作用发生的顺序”?

\n

Cal*_*eth 1

使用同一标量对象的值进行值计算。x[i]使用 的值i

从C11开始,赋值存在顺序关系。

更新左操作数的存储值的副作用在左操作数和右操作数的值计算之后排序。

(C11 6.5.16/3)

在此之前,标准讨论表达式的方式较为宽松。它没有描述先序关系。相反,我们有:

在上一个和下一个序列点之间,对象的存储值最多应通过表达式的求值修改一次。此外,应只读先前值以确定要存储的值。

您没有读取该值“除了确定要存储的值”,因此定义了行为。

(C99 6.5/2)