3
#include <stdio.h> int main() { int a = 20, b = 30; a = a + b; b = a - b; a = a - b; return 0; } 

Can I use this program to swap both positive and negative values.

8
  • 14
    The preferred way to swap two variables is with a temporary. Don't try using quirky code. Remember KISS: Keep It Simple, S****d. Commented Jun 3, 2017 at 13:30
  • 1
    Plus, It's better to let the compiler do this optimization because it will know the one who is the faster on your actual system. They are not many situation where this algorithm is better than a temporary variable. en.wikipedia.org/wiki/XOR_swap_algorithm. Commented Jun 3, 2017 at 13:34
  • Remember, under optimization that temporary will likely be elided and the values merely stored in registers anyway. Commented Jun 3, 2017 at 13:37
  • As long as the arithmetic doesn't cause overflow, you code should be OK, though it is unusual to use arithmetic. But it is better by far to simply use a temporary. Commented Jun 3, 2017 at 13:39
  • 3
    No. There is no preferred way to swap without temp. Commented Jun 3, 2017 at 14:35

5 Answers 5

7

The algorithm for swapping variables without a temporary holder uses the bitwise XOR operation, not subtraction. So, using variables named a and b, we'd have:

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

EDIT: Your code does work for the few cases I tested it with using some integral values for a and b, but XOR is the conventional way of doing it. As commenter @wildplasser pointed out, the reason XOR is the convention is that integer addition and subtraction can overflow, giving incorrect results, whereas XOR cannot.

Sign up to request clarification or add additional context in comments.

5 Comments

The reason for this is that integer addition can overflow, and the behaviour at integer overflow is undefined. XOR cannot overflow
Your first sentence is incorrect. XOR swap is not the only way to swap without a temporary variable
also, even case of overflow, when you add something with overflow and then substract the same thing, you get underflow and the same previous value (even against the hordes of defenders of the undefined behaviour thing) so, I'm afraid that theoretically, using xor or + and - is equivalent. Overflowing registers is some kind of modular arithmetic, well known since long ago, and for this case sum and exclusive or are equivalent operations.
@LuisColorado Signed integer overflow is undefined by the C standard.
This method does not work if a and b refer to the same object. Neither does the addition/subtraction approach in the question.
4

This method will not work if a+b overflows as this invokes undefined behavior.

It's better to use the XOR method. Even better, use a temp anyway as it's more clear.

4 Comments

i'm not going to discuss this, but I'm afraid not. Even with overflow, there's no undefined behaviour in modular arithmetic (what is what happens in this case) Of course, you can get some implementation written ex-profeso to fail in this case, and it will be completely standard compliant. But, can you cite just one in which behaviour is different? We are getting to far with the U.B. feature...
And to Luis Colorado's point, by the same token, it's a perfectly fine idea to hold a gun to your head and pull the trigger, as long as you know the gun is not loaded.
For the record: I took the posted code, changed a's value to 2100000000, changed b's value to 200000000, and compiled it with cc -ftrapv. As expected, the resulting program crashed, with a "trace/BPT trap".
Deciding that certain kinds of undefined behavior "can't fail" and so are "safe" is a popular sport — I've engaged in it myself — but while it's true that signed integer overflow is reliably modular by default on the vast majority of today's platforms, the actual undefinedness of it is not merely theoretical.
3

As others have pointed out, you should use XOR instead of arithmetic operators to avoid UB due to signed overflow.

But keep in mind that in most common processors (x86, ARM, 68k, etc.) 3 logical operations will be slower (and consume more energy) than 3 moves between registers. So, provided enough registers are available (which in your example is most surely the case) and optimization enabled, using a temporary will be faster than bit twiddling. Finally, some architectures have an exchange instruction (e.g. xchg on x86), a smart enough compiler should be able to use it, and that would be even faster.

The moral of the story - beware premature optimization.

Comments

3

There is no preferred way to swap two variables without using a temporary variable in C.

The preferred way to swap two variables in C is to use a temporary variable.

Swapping without using a temporary is an obsolete problem. It might once have been an interesting problem back when we were writing (a) assembly language code for (b) machines with very few registers and not much memory. But when we're writing in a higher level language like C, on a machine with ample memory and registers, there is nothing -- nothing! -- positive to be gained by trying to eliminate the temporary variable.

Asking "What's the best way to swap two variables without using a temporary?" is kind of like asking, "What's the best way to get my horse to pull my buggy without using a buggy whip?".

Swapping without using temporaries might be an interesting intellectual problem, but it is a an error-prone waste of time in any practical programming situation. The likelihood that you will improve the performance of your program by eliminating the temporary is zero. The likelihood that you will introduce subtle bugs, however, is substantially greater than zero.

1 Comment

UV'd as the best answer. You might give simple examples of subtle bugs introduced when swapping using addition/subtraction or triple xor.
1

Yep it can be used for both positive and negative values but the problem with this method is when the numbers are large a+b can go out of the range and that can lead to a strange behaviour. Using temp variable for swapping is a good and simple way so use that whenever possible.

5 Comments

there's no strange behaviour on large numbers... overflow happens and then happens back again. He is adding some number and sbstracting back the other number around 0. overflow arithmetic is modular arithmetic (signed arithmetic is also modular, with an offset) and, for this case, it's the same.
@LuisColorado You are incorrect. Overflow arithmetic is guaranteed to be modular only for unsigned integers. For signed integers, it might be (and indeed it is on many popular machines), but this is not guaranteed by the C Standard.
@SteveSummit, I'm not incorrect. I expected this answer. Can you tell me just one implementation that does not implement as said? It's incorrect from the standard perspective, but no implementation does this. 99.9999% of implementations use two's complement for signed and modulo 2^n for the unsigned ones. I know your asseveration, believe me, but after 40+ years programming in C, I haven't seen any such actual implementation (probably a C language compiler for Dr. Knuth's MIX virtual machine being the most notable possibility, as this machine doesn't use two's complement internally)
@LuisColorado When there's a compelling reason to do X, but where X is questionably valid, the question "On how many platforms does X actually not work?" can be appropriate. But here, it's doubly pointless: swapping two variables without using a temporary is basically a stupid idea to begin with, and even if you're bound and determined to do it, the "portable" solution using XOR is always available.
@SteveSummit, just to finalize, I use to be pragmatic, so I always use the temp storage solution. Even the xor approach demonstrates to be useless today in the majority of platforms. But the question was not about the most pragmatic solution, but about the possibility of doing in one well, strange way.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.