K&R C Programs Exercise 4-14

Exercise 4-14. Define a macro swap(t,x,y) that interchanges two arguments of type t. (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 _Generic is the modern alternative
  • Multi-word type limitation — a macro argument ends at a comma, so unsigned int is two arguments; typedef is 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

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>