39

Is there any built in swap function in C which works without using a third variable?

Mat
  • 202,337
  • 40
  • 393
  • 406

10 Answers10

31

No.
C++ builtin swap function: swap(first,second);
Check this: http://www.cplusplus.com/reference/algorithm/swap/

You can use this to swap two variable value without using third variable:

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

You can also check this:

https://stackoverflow.com/questions/756750/swap-the-values-of-two-variables-without-using-third-variable

How to swap without a third variable?

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Saiful
  • 1,891
  • 1
  • 15
  • 39
  • 4
    the solution with sum and difference should be avoided. With operands of signed types it can overflow and signed overflows are undefined in C. – ouah Jan 14 '12 at 12:32
  • C++ swap does _not_ work like `c=a; a=b; b=c;`. – einpoklum Dec 08 '20 at 08:58
  • Don't use XOR, and don't try to avoid a third variable. The compiler knows how to do its job better than you. – einpoklum Jan 27 '22 at 15:33
29

Why do you not want to use a third variable? It's the fastest way on the vast majority of architectures.

The XOR swap algorithm works without a third variable, but it is problematic in two ways:

  1. The variables must be distinct i.e. swap(&a, &a) will not work.
  2. It is slower in general.

It may sometimes be preferable to use the XOR swap if using a third variable would cause the stack to spill, but generally you aren't in such a position to make that call.

To answer your question directly, no there is no swap function in standard C, although it would be trivial to write.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • @delnan: I'm not trying to argue that the performance is important. All I'm saying is that there's no reason (including performance) to not want a third variable. – Peter Alexander Jan 14 '12 at 12:27
  • 9
    @delnan: `int t = a; a = b; b = t;` v.s. `a ^= b; b ^= a; a ^= b;`. Where is this wasted time? And it what universe is writing a swap significantly contributing to the time it takes you to solve a problem? This must be the biggest non-issue I have ever seen. – Peter Alexander Jan 14 '12 at 12:30
  • @delnan If you look at my post, I'm pretty sure my function is considered type-agnostic, except you have to specify the size in bytes of the values being swapped as the third argument, so I guess that doesn't _technically_ count as "not using a third variable." – Patrick Roberts Mar 06 '15 at 21:45
  • XOR Swap is mainly a trick for C programmers on embedded systems where memory is precious – A. Gille Dec 08 '20 at 10:33
10

Assuming you want a C solotion, not a C++ one, you could make it a macro, at least using GCC extension to have it generic enough, something like

 #define SWAP(x,y) do {   \ 
   typeof(x) _x = x;      \
   typeof(y) _y = y;      \
   x = _y;                \
   y = _x;                \
 } while(0)

beware of tricks like invocations swap(t[i++],i); to avoid them, use the address operator &. And you'll better use a temporary (for integers, there is a famous and useless trick with exclusive-or).

PS: I'm using two local variables _x and _y (but I could have used one local variable only) for better readability, and perhaps also to enable more optimizations from the compiler.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
8

There is no such function in standard C.

(In C++ you have std::swap().)


Maybe a macro from this question can be useful for you.

Community
  • 1
  • 1
Igor
  • 26,650
  • 27
  • 89
  • 114
7

There is no standard function in C to swap two variables.

A macro can be written this way:

#define SWAP(T, a, b) do { T tmp = a; a = b; b = tmp; } while (0)

and the macro can be called this way:

int a = 42;
int b = 2718;

SWAP(int, a, b);

Some solutions for a writing a SWAP macro should be avoided:

#define SWAP(a, b) do { a = b + a; b = a - b; a = a - b; } while (0)

when operands are of signed types an overflow can occur and signed overflow are undefined behavior.

Also a solution trying to optimize the XOR solution like this should be avoid:

#define SWAP(a, b) (a ^= b ^= a ^=b)

a is modified twice between the previous and the next sequence point, so it violates the sequence points rules and is undefined behavior.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • Isn't @BasileStarynkevitch's [version](http://stackoverflow.com/a/8862167/1593077) of the SWAP macro preferable? – einpoklum Jul 28 '13 at 08:01
  • 1
    @einpoklum: No, because not every compiler is GCC, so you can't rely on a GCC extension like `typeof(expr)`. –  Jul 28 '13 at 08:40
  • 1
    I especially love the use of `int` as the first arguments of the macro. Now we can claim that we have templates in our beloved language :-) – paxdiablo Jul 04 '17 at 03:12
  • Please consider removing the XOR-swap suggestion. – einpoklum Jan 27 '22 at 16:10
4

Since you may copy any object representation into an unsigned char array in C, the following macro allows you to swap any two objects:

#define SWAP(X,Y) \
    do { \
        unsigned char _buf[sizeof(*(X))]; \
        memmove(_buf, (X), sizeof(_buf)); \
        memmove((X),  (Y), sizeof(_buf)); \
        memmove((Y), _buf, sizeof(_buf)); \
    } while (0)

GCC will even generate optimal code for this in some cases. You might not keep your job though...

u0b34a0f6ae
  • 48,117
  • 14
  • 92
  • 101
1

There is is a C++ library function. It swaps the values of two integer variables. For example, swap(x, y); will swap the values of variables x and y. Similarly, swap(mat[i][j], mat[j][i]); will swap two values in matrix mat, namely the value in row i column j and the value in row j column i.

1
#define swap(T, x, y) \
    {                 \
        T tmp = x;    \
        x = y;        \
        y = tmp;      \
    }

int main()
{
    int a = 10;
    int b = 20;
    printf("a=%d b=%d\n", a, b);
    swap(int, a, b);
    printf("a=%d b=%d\n", a, b);

    return 0;
}
Li Kui
  • 640
  • 9
  • 21
-1

There is no built-in swap function but you can try this

a = a ^ b;

b = a ^ b;

a = b ^ a;

dmaelect
  • 151
  • 2
  • 14
Saiful
  • 1,891
  • 1
  • 15
  • 39
-2

I believe I've come up with a type-agnostic function for swapping any two values in standard C, though since I'm fairly new to the language I may have overlooked something. It uses the XOR swap algorithm, and I'm sure it could be optimized more, but it works as long as the two values point to the same number of bytes, specified by the 3rd argument:

void swapn(void *a, void *b, size_t n) {
    if (a == b) {
        return;
    }

    size_t i;
    char *x = (char *)a,
        *y = (char *)b;

    for (i = 0; i < n; i++) {
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
        x++;
        y++;
    }
}

Example usage:

// swap two integers
int x = 5,
    y = 30;

printf("%d\t%d\n", x, y);

swapn(&x, &y, sizeof(int));

printf("%d\t%d\n\n", x, y);

// swap two floats
float a = 9.23f,
    b = 6.83f;

printf("%.2f\t%.2f\n", a, b);

swapn(&a, &b, sizeof(float));

printf("%.2f\t%.2f\n\n", a, b);

// swap two doubles
double p = 4.7539,
    q = 0.9841;

printf("%.4f\t%.4f\n", p, q);

swapn(&p, &q, sizeof(double));

printf("%.4f\t%.4f\n\n", p, q);

// swap two chars
char m = 'M',
    n = 'n';

printf("%c\t%c\n", m, n);

swapn(&m, &n, sizeof(char));

printf("%c\t%c\n\n", m, n);

// swap two strings of equivalent length
char s[] = "Hello",
    t[] = "World";

printf("%s\t%s\n", s, t);

swapn(s, t, sizeof(s));

printf("%s\t%s\n\n", s, t);

The output is:

5   30
30  5

9.23    6.83
6.83    9.23

4.7539  0.9841
0.9841  4.7539

M   n
n   M

Hello   World
World   Hello
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • I'm pretty sure the three-way xor-assignment is undefined behaviour, since it assigns to `*x` twice without sequence point in between. That is easily fixed, but I don't see why one should bother with xor swap anyway. It's not faster, it's not easier, it breaks when the two parameters alias, and in this twenty line general implementation the extra variable isn't even really more code. But it seems pretty type agonistic, I'll give you that. `n` should be `size_t` though. –  Mar 06 '15 at 22:02
  • @delnan I removed the undefined behavior and changed the 3rd argument to the size_t type. What do you mean by when the "two parameters alias"? I believe that's handled by the initial if statement. – Patrick Roberts Mar 06 '15 at 23:04