i = i ++是否会在C17中重新定义好?

时间:2018-11-25 14:22:35

标签: c language-lawyer operator-precedence sequence-points c17

今天在遇到问题“ Why are these constructs using pre and post-increment undefined behavior? ”之后,我决定为我可以找到的下一个C标准获取最新的草案,并阅读更多有关它的信息。
在C17草案中发现以下段落之后不久:

  

一个   表达   是指定值计算的运算符和操作数的序列,或者   指定对象或功能,或产生副作用,或执行组合   其。 运算符的操作数的值计算在该值之前排序   计算运算符的结果   
来源:ISO/IEC 9899:2017, Section 6.5 §1 "Expressions"(使用web.archive.org链接断开)

现在我有些困惑。这不是说i = i++是定义的行为吗?这次,我查看了另一个草稿C99:

  

表达式是一个运算符和操作数的序列,它们指定值的计算,或者指定对象或函数,或者产生副作用,或者执行它们的组合。   
来源:ISO/IEC 9899:1999, Section 6.5 §1 "Expressions"

这句话简直丢了!

问题

  1. 我误会了吗?
  2. 答案是否过时?
  3. 我看错了草稿吗?

2 个答案:

答案 0 :(得分:7)

您突出显示的段落仅表示表达式i++i在对完整表达式i = i++求值之前先求值。这仍然是未定义的行为,因为在没有序列点的表达式中i被多次修改了。

该段落最初出现在C11中,因此与该版本C17相同。

答案 1 :(得分:2)

全文。在C99中,该文本用于6.5.16赋值运算符:

  

更新左操作数的存储值的副作用应为   发生在上一个和下一个序列点之间。

     

操作数的评估顺序未指定。如果试图修改   赋值运算符的结果,或者在下一个序列点之后访问它,   行为是不确定的。

在C11中将其更改为:

  

更新左操作数的存储值的副作用是   在左右操作数的值计算之后排序。的评价   操作数是无序列的。

这只是不同的(而且更糟的)措辞,两个版本的行为相同-键是C11部分的最后一个句子,这仍然会导致这种不确定的行为,因为相对于左操作数,对左操作数的求值仍然没有顺序。正确的操作数。值计算仅涉及各个操作数。

C17的文字与C11相同。因此答案是:不,i = i++;仍然是C17中未定义的行为。


仅供参考,请将其与C ++ 11(5.17)进行比较:

  

在所有情况下,赋值都在值之后排序   左右操作数的计算,以及赋值表达式的值计算之前。

这与C11大致相同,没有明确的“操作数的评估未排序”。这是C ++ 11中的一个缺陷,目前尚不清楚是否可以使某些表达式定义良好。

C ++ 17提供了一个说明(8.5.18):

  

在所有情况下,赋值都在值之后排序   左右操作数的计算,以及赋值表达式的值计算之前。   右侧操作数在左侧操作数之前排序。

因此在C ++ 17中,i=i++;的定义明确。正如我们所看到的,措辞很明确,与C11 / C17中的“未排序”相对。