【问题标题】:Why is this Undefined Behavior?为什么这是未定义的行为?
【发布时间】:2011-05-05 13:35:24
【问题描述】:

为什么以下给定的表达式会调用未定义的行为?

int i = 5;
i = (i,i++,i) + 1 

我的问题受到 Als 的question here的影响

【问题讨论】:

标签: c++ undefined-behavior sequence-points


【解决方案1】:

它不是未定义的。

这里回答了 C,Sequence points and partial order

我认为这同样适用于 C++(这是我在看到该链接之前的回复):

逗号运算符引入了一个序列点(并在一定程度上限制了表达式必须被计算的顺序——从左到右),所以:

  • i 的两个修改由一个序列点(第二个逗号)分隔。
  • i++i 的修改通过序列点与其他所有内容分开。
  • =i 的修改与表达式中最后一次出现的i 分开,但这没关系,因为我们可以访问i 并修改它没有中间序列点,前提是访问是“确定要存储的值”(5/4)。
  • 正如 Als 所说,在实践中,只要每个人都有不编写它的基本常识,该代码是否定义了行为并不重要 ;-)

【讨论】:

  • 只考虑, 是一个序列点这一事实,是的。不幸的是,标准对此非常谨慎:Note that some aspects of sequencing in the abstract machine are unspecified; the preceding restriction upon side effects applies to that particular execution sequence in which the actual code is generated.
  • 我想回答但我没有。 [又一个未定义的行为问题] ;-)
  • @Let_Me_Be:我承认我不明白那个脚注。 “按执行顺序”生成“实际代码”是什么意思?
  • @Let_Me_Be:哦,我想我明白了。实现可以选择一个表达式的合法执行序列,它选择哪个是未指定的。对副作用的限制提到了诸如“先前”和“后续”之类的术语,这些术语应根据实际选择的顺序来理解。正确的?所以在这里我们依赖两个事实(1)副作用是完整的,(2)逗号运算符指定其操作数的执行顺序(5.18 / 1:“所有副作用[左侧]都被执行在评估正确的表达式之前。")
  • 想一想,没有明确说明逗号运算符实际上是一个序列点,只是左边的所有副作用都是完整的。但是表达式的规则并没有说如果所有副作用都完整则可以修改两次,他们说如果有序列点可以修改两次。但是,5/4 中的例子清楚地将逗号视为一个序列点,所以我认为我们必须在它的语义包含序列点的语义的基础上得出它是一个的结论。
【解决方案2】:

在 C++ 中未定义为自身赋值:

i = i++

i 在这之后应该是什么?它应该是前一个值还是前一个值加一?执行顺序留给编译器,所以不同的平台会有不同的结果。

【讨论】:

  • 我很确定i 在那之后应该保持不变。由于序列点的问题,它在技术上仍然是未定义的行为,但不可能有其他结果。
【解决方案3】:

因为标准中没有定义后增量或分配中的哪一个将首先发生;由编译器实现来决定它们的顺序。

【讨论】:

    猜你喜欢
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多