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

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

a^=b^=a^=b

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

代码有什么严重错误吗?

代码有什么严重错误吗?

是!

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


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

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

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

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

编辑

正如@caf注意到b^=a^=b很好,即使未指定^=运算符的参数的计算顺序,因为表达式中b所有访问都用于计算存储在的最终值b ,行为定义明确。

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

 #include  using namespace std; // ... int x=5, y=10; // x:5 y:10 swap(x,y); // x:10 y:5 

根据R.&sellibitze的贡献:

使用逗号运算符:

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

来自短信和维基百科:

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

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

我建议你使用std :: swap()来实现c ++。

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

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

像这样做:

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

这个如何?

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

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

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

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

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