A couple of days ago I came up with a general-purpose macro for swapping values in C programs. My colleague Panagiotis Louridas suggested an improvement, and this prompted me to see the two macros got compiled.
Here is the original macro:
/* General-purpose swap macro */
#define swap2(a, b) do {\
struct s_swap { char c[sizeof(a)]; } swap_tmp; \
assert(sizeof(swap_tmp) == sizeof(a)); \
swap_tmp = *(struct s_swap *)&a; \
*(struct s_swap *)&a = *(struct s_swap *)&b; \
*(struct s_swap *)&b = swap_tmp; \
} while (0)
Here is the improved macro (Panagiotis used a = b in the second step, but that wouldn't work for arrays):
/* General-purpose swap macro */
#define swap(a, b) do {\
char c[sizeof(a)]; \
memcpy((void *)&c, (void *)&a, sizeof(c)); \
memcpy((void *)&a, (void *)&b, sizeof(a)); \
memcpy((void *)&b, (void *)&c, sizeof(b)); \
} while (0)
So, how do the macros compare with the standard code, such as the example below?
int a, b, tmp;
tmp = a;
a = b;
b = tmp;
It turns out that both gcc (3.2) and Microsoft C (11.00) treat the sequence remarkably well.
printf("a=%d b=%d\n", a, b);
swap(a, b);
printf("a=%d b=%d\n", a, b);
; Line 16
push esi
push ebx
push OFFSET FLAT:$SG196
call _printf
add esp, 12 ; 0000000cH
; Line 18
push ebx
push esi
push OFFSET FLAT:$SG201
call _printf
Last modified: Monday, January 30, 2006 10:37 am
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.