还有一个与序列点有关的问题

时间:2010-11-22 14:01:17

标签: c++

是的,我读了sequence points上的文章。但是我无法理解为什么++i = 2会调用未定义的行为? i的最终值无论如何都是2,那么为什么表达式是ub?

代码段

int main()
{
  int i =0;
  ++i=2;
  return 0;
}

抱歉,我的英语不是很好。

6 个答案:

答案 0 :(得分:11)

对您来说很明显,因为显然 i首先分配为i+1,然后第二为分配了值2

但是,这两个赋值都发生在同一个序列点中,因此由编译器决定是否发生第二次,因此不同的编译器实现可以生成会产生不同结果的代码,因此它是 UB

答案 1 :(得分:9)

观察该值将是您所声称的,这就是UB如何在其他可能的场景中表现出来的。该程序可能会输出您的预期,输出一些不相关的数据,崩溃,损坏数据或花费您所有的钱订购披萨。一旦C ++标准说某些构造是UB,你就不应该指望任何特定的行为。观察到的结果可能因程序运行而异。

答案 2 :(得分:2)

发生未定义的行为是因为编译器可以实现以下代码:

++i = 2;

作为:

i = 2;
++i;

++i;
i = 2;

在语言中未指定,编译器可以选择实现上述任一方法。第一个会产生3,第二个产生2。所以它是未定义的。

答案 3 :(得分:1)

调用++i = 2;本身并不会调用未定义的行为;如果需要,任何编译器都可以在到达该代码时执行非常明确的操作。但是c ++标准规定这样的操作是未定义的,因此编译器可能会做一些意外的事情(比如删除C盘上的所有文件或向教皇发送文本消息)并且仍然是兼容的编译器。唯一能使UB成为标准的是UB。

也许最重要的一点是,编译器的一个版本可能会执行与同一编译器的下一个版本不同的操作。

答案 4 :(得分:0)

从您提供的完全相同的链接:

  
      
  • 此外,先前的值应为   只访问以确定值   待存储。
  •   
     

这是什么意思?这意味着,如果一个   对象被写入一个完整的   表达式,对它的任何和所有访问   必须在同一个表达式内   直接参与计算   要写的价值。

此处在运算符=的左侧,对i的访问不参与计算值的计算。

答案 5 :(得分:0)

++ i(应该是)rvalue,因此不能用作左值,但是(++ i)= 2;应该工作正常。我不相信这是UB,但是,一如既往,我可能是错的。