“在不使用第三个变量的情况下交换两个变量的值”中的潜在问题

时间:2010-09-18 11:08:16

标签: c++ c swap operator-precedence

我最近使用这种方法来交换两个变量的值而不使用第三个变量。

a^=b^=a^=b

但是当我在不同的编译器上尝试上面的代码时,我得到了不同的结果,有些给出了正确的结果,有些则没有。

代码有什么严重错误吗?

8 个答案:

答案 0 :(得分:39)

  

代码有什么严重错误吗?

是!

a^=b^=a^=b实际上在C和C ++中调用未定义的行为,因为您试图在两个序列点之间多次更改a的值。


尝试写作(虽然不是万无一失)

a ^= b;
b ^= a;
a ^= b;

而不是a^=b^=a^=b

P.S :不要尝试在不使用第三个变量的情况下交换两个变量的值。始终使用第三个变量。

编辑

由于注意b^=a^=b运算符的参数的评估顺序未指定,@caf注意^=是正常的,因为表达式中b的所有访问都是用于计算存储在b中的最终值,行为已明确定义。

答案 1 :(得分:16)

如果您正在使用C ++,为什么不在STL中使用交换算法?它非常适用于此目的,它非常清楚它的作用:

#include <algorithm>
using namespace std;

// ...

int x=5, y=10;    // x:5 y:10
swap(x,y);        // x:10 y:5

答案 2 :(得分:5)

基于来自R.&amp; S的贡献。 sellibitze:

使用逗号运算符:

 (a^=b,b^=a,a^=b);

来自文字&amp;维基百科:

“逗号运算符可用于将相关表达式链接在一起。表达式的逗号链接列表从左到右进行计算,最右边表达式的值是组合表达式的值。充当序列点。“

“序列点保证先前评估的所有副作用都已执行,并且尚未执行后续评估的副作用。它消除了由于执行不明确的顺序而产生的未定义行为。原始表达。“

答案 3 :(得分:5)

我建议您对c ++使用std :: swap()。

对于c,请使用此宏。请注意,您需要首先比较a和b,否则当它们指向相同的内存位置时,您将清除该值并且它将变为0.

#define swap(a, b)  ((a) == (b) || (a) ^= (b), (b) ^= (a), (a) ^= (b))

答案 4 :(得分:4)

这样做:

a ^= b;
b ^= a;
a ^= b;

答案 5 :(得分:1)

这个怎么样?

a = a + b;
b = a - b;
a = a - b;

答案 6 :(得分:0)

我想知道为什么没有人建议将表达式括起来。似乎它不再是UB了。

a^=(b^=(a^=b));

答案 7 :(得分:0)

您也可以尝试以下方法,但如果数字足够大,则值会溢出

a=a*b;
b=a/b;
a=a/b;