参考this问题。
我已多次尝试过这个相同的程序,我看到其他人(朋友组)使用相同的逻辑进行交换,但没有人发现错误的输出。我想问一下,由于序列点,有可能出错输出。
答案 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;而不是标准swap
,Visual Studio,你会有一个令人不快的惊喜。评估的副作用仍然存在。
答案 5 :(得分:0)
C标准(1999年版)在6.5节第2节中说:
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。此外,先前的值应该是只读的,以确定要存储的值。
所以,是的,这段代码违反了序列点规则(b
是从中读取的,但不是为了确定b
的新值。 C ++从C继承了它。