Is there a built-in way to swap two variables in C?

I know how to swap two variables in C++, ie you use std::swap(a,b).

Does the C standard library have a similar function to C++'s std::swap(), or do I have to define it myself?


You need to define it yourself.

  1. C doesn't have templates.

  2. If such function does exist it would look like void swap(void* a, void* b, size_t length), but unlike std::swap, it's not type-safe.

  3. And there's no hint such function could be inlined, which is important if swapping is frequent (in C99 there's inline keyword).

  4. We could also define a macro like

     #define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
    

    but it shadows the ttttttttt variable, and you need to repeat the type of a. (In gcc there's typeof(a) to solve this, but you still cannot SWAP(ttttttttt,anything_else);.)

  5. And writing a swap in place isn't that difficult either — it's just 3 simple lines of code!


There is no equivalent in C - in fact there can't be, as C doesn't have template functions. You will have to write separate functions for all the types you want to swap.


You can do something similar with a macro if you don't mind using a gcc extension to the C language, typeof:

#include <stdio.h>

#define SWAP(a, b) do { typeof(a) temp = a; a = b; b = temp; } while (0)

int main(void)
{
    int a = 4, b = 5;
    float x = 4.0f, y = 5.0f;
    char *p1 = "Hello";
    char *p2 = "World";

    SWAP(a, b); // swap two ints, a and b
    SWAP(x, y); // swap two floats, x and y
    SWAP(p1, p2); // swap two char * pointers, p1 and p2

    printf("a = %d, b = %d\n", a, b);
    printf("x = %g, y = %g\n", x, y);
    printf("p1 = %s, p2 = %s\n", p1, p2);

    return 0;
}

This works quickly in Clang and gcc (but not icc, which doesn't recognize this swap function - however, it will compile in any standard C99 compiler), provided that the optimizations actually recognize the swap (they do on high enough optimization levels).

#include <string.h>

#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
static inline void swap_internal(void *a, void *b, size_t size) {
    char tmp[size];
    memcpy(tmp, a, size);
    memmove(a, b, size);
    memcpy(b, tmp, size);
}

Now for explaining how it works. First, the SWAP() line is relatively strange, but it's actually relatively simple. &(a) is argument a passed as a pointer. Similarly, &(b) is argument b passed as an pointer.

The most interesting piece of code is sizeof *(1 ? &(a) : &(b)). This is actually a relatively clever piece of error reporting. If error reporting wouldn't be needed, it could be just sizeof(a). Ternary operator requires that its operations have compatible types. In this case, I check two different arguments for their type compatibility by converting them to pointer (otherwise, int and double would be compatible). As int * and double * aren't compatible, compilation would fail... provided it's standard C compiler. Sadly, many compilers assume void * type in this case, so it fails, but at least with a warning (that is enabled by default). To ensure correct size of the result, the value is dereferenced, and applied to sizeof, so there are no sideeffects.

~/c/swap $ gcc swap.c
swap.c: In function ‘main’:
swap.c:5:64: warning: pointer type mismatch in conditional expression [enabled by default]
 #define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
                                                                ^
swap.c:16:5: note: in expansion of macro ‘SWAP’
     SWAP(cat, dog);
     ^
~/c/swap $ clang swap.c
swap.c:16:5: warning: pointer type mismatch ('int *' and 'double *') [-Wpointer-type-mismatch]
    SWAP(cat, dog);
    ^~~~~~~~~~~~~~
swap.c:5:57: note: expanded from macro 'SWAP'
#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
                                                        ^ ~~~~   ~~~~
1 warning generated.
~/c/swap $ icc swap.c
swap.c(16): warning #42: operand types are incompatible ("int *" and "double *")
      SWAP(cat, dog);
      ^

This macro evaluates everything exactly once (sizeof is special, as it doesn't evaluate its arguments). This provides safety against arguments like array[something()]. The only limitation I can think of is that it doesn't work on register variables because it depends on pointers, but other than that, it's generic - you can even use it for variable length arrays. It can even handle swapping identical variables - not that you would want to do that.


In C this is often done using a macro,
there are very simplistic examples, eg:
#define SWAP(type,a,b) {type _tmp=a;a=b;b=_tmp;}
... but I wouldn't recommend using them because they have some non-obvious flaws.

This is a macro written to avoid accidental errors.

#define SWAP(type, a_, b_) \
do { \
    struct { type *a; type *b; type t; } SWAP; \
    SWAP.a  = &(a_); \
    SWAP.b  = &(b_); \
    SWAP.t  = *SWAP.a; \
    *SWAP.a = *SWAP.b; \
    *SWAP.b =  SWAP.t; \
} while (0)
  • Each argument is instantiated only once,
    so SWAP(a[i++], b[j++]) doesn't give problem side effects.
  • temp variable name is also SWAP, so as not to cause bugs if a different name happens to collide with the hard-coded name chosen.
  • It doesn't call memcpy (which in fact ended up doing real function calls in my tests, even though a compiler may optimize them out).
  • Its type-checked
    (comparing as pointers makes the compiler warn if they don't match).