40

This equation swaps two numbers without a temporary variable, but uses arithmetic operations:

a = (a+b) - (b=a);

How can I do it without arithmetic operations? I was thinking about XOR.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Vishwanath Dalvi
  • 35,388
  • 41
  • 123
  • 155
  • 5
    Why would you want to do this? – Mark Byers Sep 05 '10 at 19:01
  • read this prb in 1 book.. thats y . how to swap without arithmetic operators – Vishwanath Dalvi Sep 05 '10 at 19:03
  • @sorry guys i edited my question.. its without temp .. and without arithmetic operator – Vishwanath Dalvi Sep 05 '10 at 19:06
  • @mr_eclair: 1) please spell out your words, it's much more readable. 2) review the article Oli posted below for reasons why you don't want to swap like this in practice. – Michael Petrotta Sep 05 '10 at 19:06
  • 12
    Behaviour of that code is undefined, by the way. Both `a` and `b` are read and written without an intervening sequence point. For starters, the compiler would be well within its rights to evaluate `b=a` before evaluating `a+b`. – Steve Jessop Sep 05 '10 at 19:13
  • 7
    why the downvotes for the question guys? he asked this out of curiousity. It was a nice question and it let many of us learn about this method and also its disadvantages. Come on guys what's wrong with you? one upvote to even out. – Sandeepan Nath Sep 05 '10 at 19:17
  • 2
    @sandeepan: I didn't downvote, but I won't vote up. The code he contends will swap variable values is broken. Naive people will happen across this post, see the code, and happily plop it in their work. Downvotes are a way to warn J. Coder, that maybe that's not a good idea. – Michael Petrotta Sep 05 '10 at 19:26
  • @Michael Petrotta, Maybe people shouldn't copy/paste code from any question asked on SO without reading the topic first... And the OP post doesn't contain code. – Colin Hebert Sep 05 '10 at 19:29
  • 1
    @Colin: that's a strange comment. People will post code they see on the net, that's what they do. Let's help them avoid shooting themselves in the foot, that's what we're here for. And the OP post *does* contain code, did you read it? – Michael Petrotta Sep 05 '10 at 19:31
  • @Michael, I understand that and so attaching cautionary notes like Oli Charlesworth has done in his answer is enough for that, I think. Nobody can always protect these people who just copy and paste code **without** realising the pros and cons. – Sandeepan Nath Sep 05 '10 at 19:35
  • @Michael, the OP states that it's an equation, not a statement, but you're right, the semicolon can indicate a classic statement (which won't work) – Colin Hebert Sep 05 '10 at 19:36
  • 3
    The "arithmetic" method in the question is incorrect; it **does not work** in the languages for which this question is tagged (C, C++, ObjC). – R.. GitHub STOP HELPING ICE Sep 05 '10 at 19:44
  • 3
    -1 for a useless question. You got your XOR answer, and now you comment saying it's not good enough. Of course it's not, it's the stupid XOR trick. Use a temporary variable and be done with it. If you have an actual problem or a real question, ask it. Voting to close. – GManNickG Sep 05 '10 at 19:59
  • To be painfully clear about what R and Michael say: the code above invokes undefined behavior because there is no sequence point between the two uses of `b`. How a compiler renders that line (if indeed it renders it at all) can not be relied upon. – dmckee --- ex-moderator kitten Sep 05 '10 at 20:08
  • 2
    In addition to the observations above; the temporary (a+b) just happens to be nameless. – MSalters Sep 06 '10 at 08:47
  • Here it is [enter link description here][1] [1]: http://stackoverflow.com/a/17297099/1079945 – DareDevil Jun 25 '13 at 12:18
  • @SteveJessop; Yes you are right. [The code will invoke undefined behavior](http://stackoverflow.com/a/20800762/2455888). – haccks Dec 27 '13 at 18:35
  • 1
    I would prefer temporary variable for swapping instead of going with XOR swapping or arithmetic operations. Mainly if I deal with unsigned byte, probability of getting wrong answers is high. So better avoid such methods... – Sudhakar Chavali Aug 04 '14 at 07:25
  • **Don't ever do this**. Think about it: you're telling the compiler you want to load two variables into registers, then swizzle them around a bunch of times with a lot of register loads and stores and three XOR calculations to swap them. As opposed to using a temp variable that an optimizing compiler will elide anyway and implement the swap by just loading the two values into two registers and then storing them directly. – Andrew Henle Aug 12 '21 at 20:47

10 Answers10

25
a=a+b;
b=a-b;
a=a-b;

This is simple yet effective....

sreejith k s
  • 303
  • 4
  • 2
23

Why not use the std libs?

std::swap(a,b);
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 4
    I think the asker wants a solution involving the lower level details here, not just calling a ready made function/library. – Sandeepan Nath Sep 05 '10 at 19:42
  • 7
    @sandeepan: It is not for me or you to interpret what the question is. We should answer the question stated with the best solution to the problem (if it is not what the OP requires then we will not get a check-mark). But I stand by this being the best solution to the question being asked (even the OP is actually playing with silly interview type questions). – Martin York Sep 05 '10 at 19:47
  • 7
    @Martin I disagree, we should interpret and understand well before answering and keep thinking whether we interpreted correctly. This question is not about an optimised/best solution, it is just about a different solution. – Sandeepan Nath Sep 05 '10 at 20:06
  • Well, the obvious reason not to use this library function would be that it doesn't work in 2/3 of the languages being asked about. – Chuck Sep 05 '10 at 20:10
  • @Chunk: 1/3 (it should work on objective-C (well objective-C++)) – Martin York Sep 05 '10 at 20:16
  • 3
    @sandeeoan: The thing is I do understand the question and what he wants. But I "gave him what he needs not what he wants" and as such he should become a better developer for it. – Martin York Sep 05 '10 at 20:26
  • @Foo Bah: True. But the question is marked C++ so they must expect C++ answers. – Martin York Aug 25 '11 at 05:07
  • @Foo Bah: Yes. But so what. It is marked C++ so you must expect a C++ answer. No answer will be optimal for multiple languages. XOR swap (is fun as trivial stupid example) but silly for C/C++ and objective C. Sure you can write your own swap_tmp() this is fine for C/objective-C but silly for C++ (as it is already defined with a more optimal version in C++) – Martin York Aug 25 '11 at 05:44
  • 3
    @Martin there is no indication in your reply that this is C++ specific. The XOR swap, for example, works everywhere. But there is no equivalent to the c++ swap in C standard library. – Foo Bah Aug 25 '11 at 17:23
  • @Foo Bah: The XOR example is a pointless toy example that would never be used in real life (in any language (If you think it is feel free to ask it as a question on SO)). My answer is a practical solution to the question which is the prefect answer for C++. There is no point explicitly stating it is C++ that is obvious from the context. – Martin York Aug 25 '11 at 18:09
  • @Martin it is not obvious from context, unless you knew C and objective C, that the solution only applies to C++. It would help if you explicitly wrote that. – Foo Bah Aug 25 '11 at 18:34
  • @Foo Bah: If you don't know C/Objective-C or C++ you are not going to be reading the question! – Martin York Aug 25 '11 at 18:54
21

In C this should work:

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

OR a cooler/geekier looking:

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

For more details look into this. XOR is a very powerful operation that has many interesting usages cropping up here and there.

Box Box Box Box
  • 5,094
  • 10
  • 49
  • 67
BiGYaN
  • 6,974
  • 5
  • 30
  • 43
  • 1
    thanks for XOR .. bt XOR operation is very slower any other method to solve this problem ? – Vishwanath Dalvi Sep 05 '10 at 19:19
  • @mr_eclair: On any typical platform, you're not going to get any faster than KennyTM's suggestion up at the top. – Oliver Charlesworth Sep 05 '10 at 19:28
  • 2
    To make it even less readable you could use the comma operator: a^=b, b^=a, a^=b; – Martin York Sep 05 '10 at 19:28
  • @mr_eclair: What do you mean it's slower? The *method* is to use a damn temporary variable. (Use `std::swap`.) That's it. What's the point of this question? Do you have an actual problem? – GManNickG Sep 05 '10 at 19:58
  • 1
    To make this even worse: `a ^= b ^= a ^= b` (or, even worse, `a^=b^(b=a)`) – Tim Oct 19 '15 at 20:57
  • @mr_eclair actually on hardware level summation is much slower than xor – Slava Mar 21 '17 at 17:27
  • At the hardware level, xor is a simpler operation than add or subtract. There is good reason to think that it could be faster. It was faster on old hardware, but performance may be indistinguishable on modern hardware. – Jeff Grigg May 25 '18 at 12:47
17

The best way to swap two numbers without using any temporary storage or arithmetic operations is to load both variables into registers, and then use the registers the other way around!

You can't do that directly from C, but the compiler is probably quite capable of working it out for you (at least, if optimisation is enabled) - if you write simple, obvious code, such as that which KennyTM suggested in his comment.

e.g.

void swap_tmp(unsigned int *p)
{
  unsigned int tmp;

  tmp = p[0];
  p[0] = p[1];
  p[1] = tmp;
}

compiled with gcc 4.3.2 with the -O2 optimisation flag gives:

swap_tmp:
        pushl   %ebp               ;  (prologue)
        movl    %esp, %ebp         ;  (prologue)
        movl    8(%ebp), %eax      ; EAX = p
        movl    (%eax), %ecx       ; ECX = p[0]
        movl    4(%eax), %edx      ; EDX = p[1]
        movl    %ecx, 4(%eax)      ; p[1] = ECX
        movl    %edx, (%eax)       ; p[0] = EDX
        popl    %ebp               ;  (epilogue)
        ret                        ;  (epilogue)
Matthew Slattery
  • 45,290
  • 8
  • 103
  • 119
9

I haven't seen this C solution before, but I'm sure someone has thought of it. And perhaps had more posting self-control than I do.

fprintf(fopen("temp.txt", "w"), "%d", a);
a = b;
fscanf(fopen("temp.txt", "r"), "%d", &b);

No extra variables!

It works for me, but depending on the stdio implementation you may have to do something about output buffering.

Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75
9

Using XOR,

void swap(int &a, int &b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

One liner with XOR,

void swap(int &a, int &b)
{
    a ^= b ^= a ^= b;
}

These methods appear to be clean, because they don't fail for any test-case, but again since (as in method 2) value of variable is modified twice within the same sequence point, it is said to be having undefined behavior declared by ANSI C.

Shubham A.
  • 2,446
  • 4
  • 36
  • 68
4

C++11 allows to:

  • Swap values:

    std::swap(a, b);
    
  • Swap ranges:

    std::swap_ranges(a.begin(), a.end(), b.begin());
    
  • Create LValue tuple with tie:

    std::tie(b, a) = std::make_tuple(a, b);
    
    std::tie(c, b, a) = std::make_tuple(a, b, c);
    
k06a
  • 17,755
  • 10
  • 70
  • 110
3
a =((a = a + b) - (b = a - b));
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Syed Raza Mehdi
  • 4,067
  • 1
  • 31
  • 47
-1

In addition to the above solutions for a case where if one of the value is out of range for a signed integer, the two variables values can be swapped in this way

a = a+b;
b=b-(-a);
a=b-a;
b=-(b);
Katie
  • 452
  • 7
  • 18
-2

Multiplication and division can also be used.

 int x = 10, y = 5;

 // Code to swap 'x' and 'y'
 x = x * y;  // x now becomes 50
 y = x / y;  // y becomes 10
 x = x / y;  // x becomes 5
Moiz Sajid
  • 644
  • 1
  • 10
  • 20