Exercise 4-14. Define a macro
swap(t,x,y)that interchanges two arguments of typet. (Block structure will help.)
A three-argument swap macro: t is the type, x and y are the variables to swap. The block { ... } creates a local scope for the temporary, preventing name leakage. The conventional temp variable name _swap_tmp (with an underscore prefix) reduces the chance of accidentally shadowing a caller variable named tmp.
Solution
/* K&R Exercise 4-14 — swap(t,x,y) macro
* Compile: gcc -ansi -Wall ex4-14.c -o ex4-14 */
#include <stdio.h>
#define swap(t, x, y) { t _swap_tmp = (x); (x) = (y); (y) = _swap_tmp; }
int main(void)
{
int a = 1, b = 2;
swap(int, a, b);
printf("a=%d b=%d\n", a, b); /* a=2 b=1 */
double p = 3.14, q = 2.71;
swap(double, p, q);
printf("p=%g q=%g\n", p, q); /* p=2.71 q=3.14 */
char ca = 'X', cb = 'Y';
swap(char, ca, cb);
printf("ca=%c cb=%c\n", ca, cb); /* ca=Y cb=X */
return 0;
}
Compile and Run
gcc -ansi -Wall ex4-14.c -o ex4-14
./ex4-14
Sample Output
a=2 b=1 p=2.71 q=3.14 ca=Y cb=X
Pitfalls and Limitations
/* Types with spaces don't work directly */
swap(unsigned int, a, b) /* ERROR: macro sees 3 args: unsigned / int / a */
/* Workaround: use typedef */
typedef unsigned int uint;
swap(uint, a, b); /* OK */
/* do { } while(0) pattern for safer use in if/else */
#define swap2(t, x, y) do { t _tmp = (x); (x) = (y); (y) = _tmp; } while(0)
if (cond)
swap2(int, a, b); /* safe — braces in do..while prevent dangling-else issues */
else
something();
The do { } while(0) variant is preferred in production code (Linux kernel macros use it universally) because it behaves syntactically like a single statement — the trailing semicolon after swap2(int,a,b); completes the do...while, whereas a bare { } block leaves a stray semicolon that can break an if/else chain.
What This Exercise Teaches
- Block scope in macros — braces let you declare a temporary without it leaking into the surrounding scope
- Type parameter in macros — C has no generics; passing the type as a macro argument is the classical workaround; C11
_Genericis the modern alternative - Multi-word type limitation — a macro argument ends at a comma, so
unsigned intis two arguments;typedefis the escape hatch do { } while(0)— the idiomatic wrapper for multi-statement macros; eliminates the dangling-else gotcha
Set Up Your C Environment
← Exercise 4-13 |
Chapter 4 Solutions |
Chapter 5 Solutions →
Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie