28

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?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Dr Deo
  • 4,650
  • 11
  • 43
  • 73
  • 1
    There's a newer question with an interesting answer not represented here: http://stackoverflow.com/questions/3982348/implement-generic-swap-macro-in-c – Mark Ransom Oct 20 '10 at 21:53
  • 1
    More answers (probably should be merged): http://stackoverflow.com/questions/3982348/implement-generic-swap-macro-in-c – M.M Mar 23 '15 at 05:21

14 Answers14

25

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!

TylerH
  • 20,799
  • 66
  • 75
  • 101
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 6
    To avoid shadowing `ttttttttt`, (or causing a bug if that variable is passed in as an argument). you can call the variable `SWAP` too. – ideasman42 Mar 22 '15 at 16:25
18

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.

  • so c has no standard library algorithms? swapping is a commonly used feature – Dr Deo Apr 14 '10 at 14:00
  • 1
    @Dr: C doesn't have a default data structure library. – kennytm Apr 14 '10 at 14:02
  • 9
    @Dr Deo C doesn't have lots of things that C++ does - that's kind of the point. –  Apr 14 '10 at 15:04
  • Outside of writing your own sorting algorithm, what would it be needed for? And C already has qsort(). – Ken Apr 14 '10 at 15:05
  • 2
    @Ken actually, in C++ swap() is used in all sorts of "creative" ways! Most of which would not admittedly apply to C code. –  Apr 14 '10 at 15:19
  • 3
    Since this is often done in a macro, its not quite correct to say *"You will have to write separate functions for all the types you want to swap"* – ideasman42 Mar 22 '15 at 16:23
14

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;
}
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • The problem with this implementation (portability aside) is that it will blindly swap anything, without regard to semantics (for example if dynamic memory allocation is involved). The C++ swap will call constructors and destructors appropriately to handle this. Downvote wasn't me, BTW. –  Apr 14 '10 at 16:15
  • 2
    @Neil: true, but the OP was specifically asking for a `C` implementation. It's far from a perfect solution, but it's a reasonable solution for a significant subset of C applications (IMNVHO). – Paul R Apr 14 '10 at 17:12
  • 1
    You could implement this using C11's _generic expressions. – Casper Beyer Nov 06 '12 at 06:02
  • 2
    @CasperBeyer I don't see how that would work for `struct` types – M.M Mar 23 '15 at 05:21
  • 1
    If one is going to use a GCC extension, why not two? :-) Use a _statement expression_ instead of the _do while_. – Greg A. Woods May 08 '15 at 22:50
  • 1
    @GregA.Woods: A statement-expression is only useful if you want to return a value. The do{}while() idiom for macros is well-understood, and everyone knows that it's safe even when substituted into an `if (foo) SWAP() else ...` context. I might have to stop and think about it if it was `({...; b = temp; })`. It doesn't take much extra mental time to see that that's ok too, but it's non-zero and I don't see the benefit of having it evaluate to the final value of `b` (or `a`). – Peter Cordes Sep 19 '16 at 23:10
  • 1
    My suggestion would be to use `_tmp`, to make sure you don't have a problem when someone writes `int x=1, temp = 0; SWAP(temp, x);`. Or, as @ideasman42 pointed out on another answer, use SWAP as the tmp var name. It won't expand inside the macro of the same name. (That's more confusing to read, though.) GNU C headers frequently use `_`-prefixed names for temporaries inside macros, since user code shouldn't be using those var names itself (It's ok to shadow globals of those names, only a problem if user code actually does `SWAP(_tmp, x)`). – Peter Cordes Sep 19 '16 at 23:15
  • 1
    I think you missed the point of, i.e. the benefit of, the more generic nature of using a _statement expression_ @PeterCordes. They are usable even if they don't return a (useful/desired) value, and given the (ab)use of one language extension, the use another which, for all intents and purposes, always accompanies the first affords the additional flexibility at zero additional cost. I would also argue a macro using a _statement expression_ is also far more readable in both its original form and also in the preprocessor output. – Greg A. Woods Sep 20 '16 at 04:19
  • 1
    @GregA.Woods: I got that that was at least part of your point, and (slightly) disagreed with it. `do{}while(0)` is a very standard idiom for macros, and is *more readable* since it's what I'd be looking for to make sure the macro was written in the usual safe way. If I don't see that, I'd spend an extra second looking more closely to see what is going on. If you have other macros that also use statement-expressions (like min and max), it would be very reasonable to use one for this, too, though. Either way, I don't think I'd change it in an existing codebase, not worth the diff noise. – Peter Cordes Sep 20 '16 at 04:45
  • 1
    TL:DR: it's not just compiler support, it's about human reader support. Not everyone is even familiar with the statement-expression extension. (Although they should be, because they're great!) – Peter Cordes Sep 20 '16 at 04:46
9

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.

Konrad Borowski
  • 11,584
  • 3
  • 57
  • 71
  • This will probably defeat some optimizations in most compilers. Many are pretty good at seeing through this kind of use of memcpy, but definitely not perfect. I would highly recommend not using this if you care about performance. At best this might make an `#ifdef` fallback for compilers that don't support GNU extensions, specifically `typeof()`. – Peter Cordes Sep 19 '16 at 23:04
  • Another option for implementing `swap_internal`, although not very efficient, is to do the swap a byte at a time: `static inline void swap_internal(void *a, void *b, size_t size) {` `char *x = a;` `char *y = b;` `char t;` `while (size--) {` `t = *x;` `*x++ = *y;` `*y++ = t;` `}` `}`. It may be useful if VLAs are not supported or if memory is tight. – Ian Abbott Jun 14 '21 at 16:29
3

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).
ideasman42
  • 42,413
  • 44
  • 197
  • 320
  • You're using a struct instead of three separate variables since SWAP is the only name it's absolutely guaranteed to be safe to use, right? (So you can only have one variable). Another option is to use things like `_a`, `_b`, and `_tmp`, since code using your macro should not be touching any _prefixed variables. It's ok to shadow a global called `_a` inside your macro, since no use of the macro should involve `SWAP(_a, x)`. But your way avoids this source of breakage even in bad programs that use reserved names for their own vars. – Peter Cordes Sep 19 '16 at 23:22
  • Right, and some projects use `-Wshadow` so it's nice to be able to rule this out even as an unlikely possibility. – ideasman42 Nov 06 '17 at 02:23
1

Check your compiler documentation. The compiler may have a swapb function for swapping bytes and my provide other similar functions.

Worst case, waste a day and write some generic swap functions. It won't consume a significant amount of your project's schedule.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

Another macro not already mentioned here: You don't need to give the type if you give the temporary variable instead. Additionally the comma operator is useful here to avoid the do-while(0) trick. But usually I don't care and simply write the three commands. On the other hand a temporary macro is useful if a and b are more complex.

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

void mix_the_array (....)
{
    int tmp;
    .....
    SWAP(pointer->array[counter+17], pointer->array[counter+20], tmp);
    .....
}

#undef SWAP
Secure
  • 4,268
  • 1
  • 18
  • 16
0

in essence, swap function is to swap two memory block. with two addresses and the size of block in bytes, we can swap pointers, integers, doubles, arrays, structs, ...

a pointer has three parts, e.g. we can break down short* p into three pieces

  1. address: void* p
  2. size: reading two bytes at void*p, we get a short integer.
  3. usage: e.g. print a short integer with %hu

using the first two parts, we will be able to build a generic swap function:

#include<stdint.h> 
#ifdef _WIN32
#define alloca _alloca
#else
#include <alloca.h>
#endif

void gswap(void * const a, void * const b, int const sz) {
    // for most case, 8 bytes will be sufficient.
    int64_t tmp; // equivalent to char tmp[8];
    void * p;
    bool needfree = false;
    if (sz > sizeof(int64_t)) {
        // if sz exceed 8 bytes, we allocate memory in stack with little cost.
        p = alloca(sz);
        if (p == NULL) {
            // if sz is too large to fit in stack, we fall back to use heap.
            p = malloc(sz);
            //assert(p != NULL, "not enough memory");
            needfree = true;
        }
    }
    else {
        p = &tmp;
    }

    memcpy(p, b, sz);
    memcpy(b, a, sz);
    memcpy(a, p, sz);

    if (needfree) {
        free(p);
    }

}

e.g.:

{// swap int 
    int a = 3;
    int b = 4;
    printf("%d,%d\n", a, b);//3,4
    gswap(&a, &b, sizeof(int));
    printf("%d,%d\n", a, b);//4,3
}
{// swap int64
    int64_t a = 3;
    int64_t b = 4;
    printf("%lld,%lld\n", a, b);//3,4
    gswap(&a, &b, sizeof(int64_t));
    printf("%lld,%lld\n", a, b);//4,3
}
{// swap arrays
    int64_t a[2] = { 3,4 };
    int64_t b[2] = { 5,6 };
    printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//3,4,5,6
    gswap(&a, &b, sizeof(a));
    printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//5,6,3,4
}
{// swap arrays
    double a[2] = { 3.,4. };
    double b[2] = { 5.,6. };
    printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//3.000000, 4.000000, 5.000000, 6.000000
    arrswap(&a, &b, sizeof(a));
    printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//5.000000, 6.000000, 3.000000, 4.000000
}
chen_767
  • 337
  • 2
  • 8
0

Some of the swapping mechanism involve -

//( Not quite good, try passing ++x and ++y as arguments :-} )
#define SWAP_0(x,y) { x = x+y; \
                      y = x-y; \
                      x = x-y; }

//Faster than SWAP_0
#define SWAP_1(x,y) { x ^= y; \
                      y ^= x; \
                      x ^= y; }

//Optimal for general usage
#define SWAP_2(x,y)                                                                         \
                 do                                                                         \
                {                                                                           \
                    uint8_t __temp[sizeof(x) == sizeof(y) ? (signed)sizeof(x) : -1];        \
                    memcpy(__temp,     &y, sizeof(x));                                      \
                    memcpy(    &y,     &x, sizeof(x));                                      \
                    memcpy(    &x, __temp, sizeof(x));                                      \
                } while(0)

//using GCC specific extension
#define SWAP_3(x, y) do                                                                     \
                    {                                                                       \
                        typeof(x) SWAP_3 = x; x = y; y = SWAP_3;                            \
                    }while (0)

//without GCC specific extension - can be invoked like this - SWAP_3(x,y, int) or SWAP_3(x,y, float)
#define SWAP_4(x, y, T) do                                                                  \
                    {                                                                       \
                        T SWAP_4 = x; x = y; y = SWAP_4;                                    \
                    }while (0)
Ajay Rajan
  • 31
  • 4
0

one possible solution is to take a size argument, and just swap the items one byte at a time

#include <stdint.h>
#include <stdlib.h>

inline void swap_generic(void* const restrict l, void* const restrict r, const size_t size) {
    uint8_t* const left  = l;
    uint8_t* const right = r;

    for (size_t i = 0; i != size; ++i) {
        uint8_t temp_byte = right[i];
        right[i]  = left[i];
        left[i]   = temp_byte;
    }
}
Luan Vitor
  • 83
  • 6
0

Here is a solution which is arguably better than anything proposed so far:

#include <stddef.h>
#include <string.h>

inline void memswap(void * restrict buffer, void *l, void *r, size_t size) {
    memcpy(buffer, l, size);
    memmove(l, r, size);
    memcpy(r, buffer, size);
}

#define swap(a, b) \
    memswap(&(struct {\
        _Static_assert(sizeof *(a) == sizeof *(b), "arguments of swap must have same size" ); \
        char _[sizeof*(a)];\
    }) {0}, (a), (b), sizeof*(a))


void example(int *x, int *y) {
    // produces same assembly instructions as
    //     int t = *x;
    //     *x = *y
    //     *y = t;
    swap(x, y);
}

The basic idea is that we make a compound literal with the same size as *a and pass this into a memswap helper function that swaps l and r with the help of the b buffer. The compound literal also contains a _Static_assert declaration which ensures that the size of *a is equal to the size of *b.

This solution has many advantages:

  • it is safer because of the additional size test
  • the macro expands to an expression, not a statement, like all the others
  • it does not rely on VLAs, so it is more portable
  • it does not declare any local variables
  • it produces optimal code, at least for GCC and clang
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
0

Following macro does this in a type-safe way and works with different types:

#include <memory.h>

#define SWAP(a, b) do { char tmp1[sizeof(a)], tmp2[sizeof(a)]; \
    memcpy(tmp1, &(a), sizeof(a)); \
    (a) = (b); \
    memcpy(tmp2, &(a), sizeof(a)); \
    memcpy(&(a), tmp1, sizeof(a)); \
    (b) = (a); \
    memcpy(&(a), tmp2, sizeof(a)); \
    } while(0)

This macro

  1. first stores original value of a in the temp buffer tmp1
  2. gets new value of a by assignment from b
  3. stores the new value of a to the temp buffer tmp2
  4. restores original value of a from tmp1
  5. gets final value of b by assignment from a
  6. finally restores the correct new value of a from tmp2

The Godbolt.org compiler explorer demonstrates that at least GCC is able to optimize this nicely already at -O2.

hyde
  • 60,639
  • 21
  • 115
  • 176
-1

Lots of nice solutions in the other answers! Just another quick swap macro for C that I came up with when reading K&R:

#define SWAP(TYPE,x,y) TYPE a = x, x=y, y=a
bleudoutremer
  • 37
  • 1
  • 6
-4

In case of numeric values (at least):

I know this is not an actual or complete answer but until now everyone has been making use of temporary variables so I thought Chris Taylors blog might be relevant to mention, it certainly does remove the need for typeof() etc.

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

or

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

In theory I suppose these techniques could be applied to strings and other types as well..

Still only three operations.

Kharar
  • 7
  • 1
    Likely to be wrong for floating-point values, so not all 'numeric' types. And the second may be UB for signed types (due to overflow). – Toby Speight Feb 15 '18 at 13:20