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

Pat*_*ck 19 c c++ swap operator-precedence

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

a^=b^=a^=b

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

代码有什么严重错误吗?

Pra*_*rav 39

代码有什么严重错误吗?

是!

a^=b^=a^=b事实上,在C和C++中调用Undefined Behavior,因为您试图a在两个序列点之间多次更改值.


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

a ^= b;
b ^= a;
a ^= b;
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:

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

  • @caf:但是```运算符的参数的评估顺序是未指定的. (5认同)
  • @crypto:因为这个交换方法只适用于整数.:-) (2认同)

Com*_* 10 16

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

#include <algorithm>
using namespace std;

// ...

int x=5, y=10;    // x:5 y:10
swap(x,y);        // x:10 y:5
Run Code Online (Sandbox Code Playgroud)

  • 公平地说,问题也标记为C. (2认同)

小智 5

根据R.&sellibitze的贡献:

使用逗号运算符:

 (a^=b,b^=a,a^=b);
Run Code Online (Sandbox Code Playgroud)

来自短信和维基百科:

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

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

  • 我认为这仍然是未定义的行为.它相当于`a = a ^(a ^ = b,b ^ = a);`并且`^`运算符的左手大小可以在括号表达式之前或之后进行求值. (2认同)
  • 当前版本已定义.但仍然不明智,因为与使用本地临时(当然会优化到寄存器)相比,现代CPU的速度很慢. (2认同)

gro*_*kus 5

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

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

#define swap(a, b)  ((a) == (b) || (a) ^= (b), (b) ^= (a), (a) ^= (b))
Run Code Online (Sandbox Code Playgroud)