Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swap trick: a=b+(b=a)*0;

Tags:

c#

swap

a=b+(b=a)*0;

This sentence can swap the value between a and b.
I've tried it with C# and it works.
But I just don't konw how it works.
e.g.

a = 1, b = 2

I list the steps of it as below:

b = a -> a = 1, b = 1
b * 0 -> a = 1, b = 1
b + 0 -> a = 1, b = 1
a = b -> a = 1, b = 1 ?

But the value of b may be wrong.
Could anyone help me? It puzzles me a lot.

like image 625
cindy Avatar asked Aug 05 '11 01:08

cindy


3 Answers

a=b+(b=a)*0;

That (b=a) in the middle is an assignment statement setting b to the current value of a with the side effect that its result is (the final value of) b. When that's multiplied by 0, you get 0, but the assignment has still happened.

The outer bit sets a to b plus the result of (b=a)*0 (which is zero). Because the original b has already been used to start setting a before the assignment in the (b=a) bit, the assignment has no effect on a. In other words, it's an atomic a = b; b = a;, swapping the two values.

C# evaluates things in a strict left to right order (unlike C and C++) to avoid a large class of subtle bugs. Note that the compiler can evaluate them in a different order but only if it can determine that it will have no effect (that's not the case here).

The snippet you posted works, but is also hideous and not a good idea, especially when you can just use the far more readable:

int t = a; a = b; b = t;

Tricks like what you see here, and the XOR swap trick, and Duff's device have no place in decent, maintainable code. They're usually a way for coders to show how clever they are but they usually just show how bad they are.

If you ever see something like that in production code, I don't think any jury in the world would convict you for hunting down the perpetrator and beating them to death with the rolled up program listing.

You should write your code as if the next person that has to maintain it is a psychopath who knows where you live - in my case, you'd be half right - I have no idea where you live :-)

like image 195
paxdiablo Avatar answered Nov 14 '22 02:11

paxdiablo


Ugh! Where did you see that?? I'm rather used to the (a ^= b; b ^= a; a ^= b;) trick, so that I at least recognize it (DON'T SHOOT! I NEVER SAID I USE IT!), but I'd have to look at that one for a minute... If you saw that in production code, please figure out who wrote it and hurt him.

As the others have said (but I'd like to emphasize it): "a = b" is an assignment, but it is also an expression with a value. That's why you can do things like "a = b = c = d" - it's not a special-case language trick; they just group as "a = (b = (c = d))", and the value of "d" folds back to all of those variables.

like image 4
c4757p Avatar answered Nov 14 '22 01:11

c4757p


  0. a=b+(b=a)*0     |             | a = 1, b = 2
  1. Evaluate b      | a=2+(b=a)*0 | a = 1, b = 2
  2. Evaluate (b=a)  | a=2+1*0     | a = 1, b = 1
  3. Evaluate 1*0    | a=2+0       | a = 1, b = 1
  4. Evaluate 2+0    | a=2         | a = 1, b = 1
  5. Evaluate a=2    |             | a = 2, b = 1
like image 3
Jacob Avatar answered Nov 14 '22 02:11

Jacob