1

I have come across a "technique" for swapping 2 variables (ints, chars or pointers) without a third temp variable , like this :

int a = Something ;  
int b = SomethingElse ;  
a ^= b ;  
b ^= a ;  
a ^= b ;

Normal way would be :

int a = Something ;  
int b = SomethingElse ;  
int temp = a ;  
a = b ;  
b = temp ;

All this is fine, but the folks who share this "technique" usually state it as without using extra space.

(A) Is this true that there is no extra space ? I think, "memory to memory copy" would require fewer instructions (machine code) compared to "memory to memory XOR operation".

int temp = a <==> move content of memory location a to memory location temp **(1 instruction)**, possibly via a register **(2 instructions)**

a ^= b <==> move contents of memory location a to register1, move contents of memory location b to register2, xor register1 and register2 (store results in register1) , move register1 to memory location a **(about 4 instructions)**

It seems that the "technique" will result in longer code and longer runtime.

(B) Is the "technique" faster (or better) in some way or in some cases ?

It seems like the "technique" is slower, uses more memory, and not really suitable for floating points.

EDIT:
It seems that there may be some Potential Duplicates :
Why don't people use xor swaps?

But this question is obviously Different:
(A) That question was closed as "Not Constructive" , where it "will likely solicit debate, arguments, polling, or extended discussion", whereas this question is looking for factual references, eg "Is something true ?" & "Is this better ?"
(B) That question is about why people do not use the "technique", while this question is about the analysis of the "technique", without looking onto why people use it or do not use it.

Community
  • 1
  • 1
Prem
  • 460
  • 1
  • 7
  • 15
  • 1
    @Prem they do so because you haven't read the "how to ask a question" so you would know this does not belong on SuperUser. StackOverflow != SuperUser. – LPChip Jul 28 '15 at 12:05
  • 1
    Indeed the XOR swap usually doesn't make sense, and in the machine code the temporary variable is usually just a register, so it's basically free. Also most architectures can't do XOR on memory and those would have to load at least one of the operands into register anyway. And if both happen to be in registers already, the swapping is basically a no-op just the compiler reassigning the registers. – Jester Jul 28 '15 at 12:11
  • 2
    All in all, it depends on the CPU architecture and compiler optimization. Run both variants through a compiler, and compare the output. That's basically all that can be said. As for clarity of code, I'd prefer the temporary, actually. – DevSolar Jul 28 '15 at 12:13
  • 2
    useless trick popular among even more useless job interviewers. – zubergu Jul 28 '15 at 12:18
  • 1
    According to [this answer](http://stackoverflow.com/questions/1826159/swapping-two-variable-value-without-using-3rd-variable) the compiler should optimize your code so the XOR is not of any improvement. And [this page](http://www.programmingsimplified.com/c-program-swap-two-numbers) shows how to use this technique with pointers to swap any kind of variables. – rpsml Jul 28 '15 at 12:18
  • I would be amazed if there was not a dup for this. Also, xor swap confusing and pointless in nearly all cases. Outside of academia, everyone just uses a temp var. – Martin James Jul 28 '15 at 12:38
  • Oh look, there are LOTS of dups, eg: http://stackoverflow.com/questions/16535461/why-dont-people-use-xor-swaps – Martin James Jul 28 '15 at 12:41
  • 1
    @zubergu yeah. The only good answer would be 'I would not use such a trick even in a an in-house utiity, never mind production code, so I have no answer of any import re. xor swaps'. – Martin James Jul 28 '15 at 12:43
  • @Jester: The extra register is "free" only if you have scratch-registers unused, otherwise using a temporary variable requires spilling a register to the stack. `xor`-swap is a small micro-optimization, but in a hot loop using all available registers, it might save some time, especially on in-order processors. – EOF Jul 28 '15 at 13:04

3 Answers3

3

There's no definitive answer: it depends too much on:

  1. the architecture of the machine (number of processors, memory cache size, etc); and
  2. the quality of the compiler's optimisation.

If all the operations are performed within registers, there is unlikely to be a performance penalty of XOR compared with copy.

If you use a third variable you could help the compiler by declaring:

register int temp;

The use of the XOR technique (or addition and subtraction, as in a-=b; b+=a; a=b-a;) dates back to when memory was a crucial resource and saving a stack entry could be very important. These days the only value of this is code obfuscation.

I have absolutely no idea what the effect of XOR would be on floating-point values, but I suspect they might be converted to integers first: you will need to try it, but there is no guarantee that all compilers will give the same result.

AFH
  • 141
  • 6
1

For lower level (e.g. assembly) "variables" no longer have a permanent location. Sometimes a variable will be in memory, but sometimes the same variable will be in one register, and sometimes in a different register.

When generating code, the compiler has to keep track of where each variable happens to be at each point. For an operation like a = b, if b is in register1 then the compiler just decides that a is now also in register1. Nothing needs to be moved or copied.

Now consider this:

// r0 contains variable a
// r1 contains variable b

    temp = a

// r0 contains variable a and variable temp
// r1 contains variable b

    a = b

// r0 contains variable temp
// r1 contains variable b and variable a

    b = temp

// r0 contains variable temp and variable b
// r1 contains variable a

If you think about this you'll realise that no data needs to be moved or copied, and no code needs to be generated. Modern CPUs are able to do "nothing" extremely quickly.

Note: If a variable is a local variable (on the stack) and isn't in a register, then the compiler should be able to do the same "renaming" to avoid moving anything. If the variable is a global variable then things get more complicated - most likely causing a load from memory and a store to memory for each global variable (e.g. 2 loads and 2 stores if both variables are global).

For XOR (and addition/subtraction) the compiler might be able to optimise it so that it becomes nothing; but I wouldn't count on it. The temporary variable moves are much more likely to be optimised well.

Of course not everything is small enough to fit in a register. For example, maybe you're swapping structures and they're 1234 bytes each. In this case the programmer might use memcpy() and the compiler has to do the copies; or the programmer might do one field at a time with XOR (or addition/subtraction) and the compiler has to do that. For these the memcpy() is much more likely to be better optimised. However, maybe the programmer is smarter, and doesn't swap the 1234 bytes of data and only swaps pointers to the data. Pointers fit in registers (even when the data they point to doesn't), so maybe no code is generated for that.

Brendan
  • 35,656
  • 2
  • 39
  • 66
0

If you are manipulating ints or doubles (or more generally, any type that hold addition and subtraction operators), you can do it like this :

int a = 5;
int b = 7;
a += b;    // a == 12, b == 7
b = a - b; // a == 12, b == 5
a -= b;    // a == 7,  b == 5
Senua
  • 543
  • 4
  • 17
  • 3
    Doesn't actually work for doubles though, consider NaN or a=+inf, b=-inf, or a=1e300, b=1. XOR works for doubles, in languages that will let you do that (C with SSE intrinsics for example). – harold Jul 28 '15 at 14:35
  • @harold : good observation – Senua Jul 28 '15 at 14:37
  • Doesn't work for `int` because the overflow that can happen at `a += b` is undefined behavior. – Pascal Cuoq Jul 28 '15 at 16:39