这个表达式a = a + b - (b = a);由于C ++中的序列点,输出错误?

时间:2016-02-11 13:21:01

标签: c++

参考this问题。

我已多次尝试过这个相同的程序,我看到其他人(朋友组)使用相同的逻辑进行交换,但没有人发现错误的输出。我想问一下,由于序列点,有可能出错输出。

6 个答案:

答案 0 :(得分:8)

C ++ 11不再具有序列点,但是,该行是未定义的行为,因为b的修改相对于其读取没有排序。

这意味着任何事情都可能发生;但总的来说,主要问题是编译器可能会重新排序事件的确切顺序。

答案 1 :(得分:3)

是的,据我所知,这是未定义的行为。这里的分号是唯一的序列点,因此未定义赋值是在相同变量被使用之前还是之后发生。

现在,如果您的所有朋友都使用相同的编译器和相同的平台,这似乎很可能,他们都会看到相同的结果,使用相同的编译器,所以这并不奇怪。这就是问题的答案。

答案 2 :(得分:1)

基本上,是的。它可能会给出错误的结果,因为在这一行中B既被写入又被读取,并且未指定首先会发生什么。

很可能你已经尝试了很多次但是你使用了相同的编译器,对吗?在这种情况下,您不太可能观察到不同的结果。对于给定相同位的代码,编译器通常会产生稳定的相同结果。

要想看到差异,您可能需要更改编译器,或者至少更改一些选项,例如更多或更少积极的优化。

这个表达式的问题在于,从理论上讲,它可以编译为:

assign b  <- a
a = a + b - a     // but now, B is already equal a

assign temp1 <- a
assign temp2 <- b
assign b  <- a
a = temp1 + temp2 - a   // here values are preserved

答案 3 :(得分:1)

是的,这是未定义的行为 它会发出以下警告

  

$ g ++ -Wall -o test test.cpp test.cpp:在函数'int main()'中:   test.cpp:11:21:警告:'b'上的操作可能未定义   [-Wsequence点]

答案 4 :(得分:1)

如果您使用上述&#34;技巧&#34;而不是标准swapVisual Studio,你会有一个令人不快的惊喜。评估的副作用仍然存在。

答案 5 :(得分:0)

C标准(1999年版)在6.5节第2节中说:

  

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

所以,是的,这段代码违反了序列点规则(b是从中读取的,但不是为了确定b的新值。 C ++从C继承了它。