Potential problem in "Exchange of values ​​of two variables without using a third variable"

I recently came up with this method to replace the values ​​of two variables without using a third variable.

a^=b^=a^=b

But when I tried the above code on different compilers, I got different results, some gave the correct results, and some did not.

Is something terribly wrong with the code?

+19
c ++ c order-of-evaluation swap
Sep 18 '10 at 11:08
source share
8 answers

Is something terribly wrong with the code?

Yes!

a^=b^=a^=b actually causes Undefined Behavior in C and C ++, because you are trying to change the value of a more than once between two points in a sequence.




Try writing (although not reliable)

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

instead of a^=b^=a^=b .

PS : never try to change the values ​​of two variables without using a third. Always use the third variable.

EDIT :

As @caf b^=a^=b noted, even if the order of evaluation of the arguments of the ^= operator ^= not specified, since all calls to b in the expression are used to calculate the final value that is stored in b , the behavior is well defined.

+39
Sep 18 '10 at 11:10
source share

If you use C ++, why not use the swap algorithm in STL? It is ideal for this purpose, and it is very clear what it does:

 #include <algorithm> using namespace std; // ... int x=5, y=10; // x:5 y:10 swap(x,y); // x:10 y:5 
+16
Sep 18 '10 at 11:25
source share

Based on R. and sellibitze materials:

Use the comma operator:

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

From the text and Wikipedia:

"The comma operator can be used to link related expressions together. The list of expressions associated with a comma is evaluated from left to right, and the value of the rightmost expression is the value of the combined expression. It acts like a sequence point."

β€œThe sequence point ensures that all side effects of previous evaluations are fulfilled, and no side effects from subsequent evaluations have yet been performed. This eliminates undefined behavior resulting from a fuzzy execution order of the original expression.”

+5
Sep 18 '10 at 12:05 on
source share

I suggest you use std :: swap () for C ++.

For c use this macro. Note that first you need to compare a and b, otherwise, when they point to the same memory location, you will destroy the value and it will become 0.

 #define swap(a, b) ((a) == (b) || (a) ^= (b), (b) ^= (a), (a) ^= (b)) 
+5
Sep 18 '10 at 13:59 on
source share

Do it like this:

 a ^= b; b ^= a; a ^= b; 
+4
Sep 18 '10 at 11:13
source share

How about this?

 a = a + b; b = a - b; a = a - b; 
+1
Jan 08 2018-11-11T00:
source share

I wondered why no one suggested bracketing the expression. This does not seem to be UB anymore.

 a^=(b^=(a^=b)); 
0
May 10 '12 at 11:16
source share

You can also try the following, but if for numbers sufficiently large the value will overflow

 a=a*b; b=a/b; a=a/b; 
0
Oct. 19 '13 at 17:15
source share



All Articles