Exercise 4-14. Define a macro swap(t,x,y) that interchanges two arguments of type t. (Block structure will help.)
#include <stdio.h> // for printf()
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define SQUARE(X) ((X) * (X))
#define IPRINT(EXPR) printf(#EXPR " = %d\n", EXPR) // integer
#define FPRINT(EXPR) printf(#EXPR " = %f\n", EXPR) // floating-point
#define DPRINT(EXPR) printf(#EXPR " = %g\n", EXPR) // scientific notation
#define SPRINT(EXPR) printf(#EXPR " = %s", EXPR) // string
#define SPRINTLN(EXPR) printf(#EXPR " = %s\n", EXPR) // string, newline
#define SPRINT2LN(EXPR) printf(#EXPR " =\n%s\n", EXPR) // string, 2 newlines
#define PRINT(EXPR) printf(#EXPR) // print message
#define PRINTLN(EXPR) printf(#EXPR "\n") // print message, newline
#define PRINTINTARRAY(ARRAY, LENGTH) \
{ \
int i; \
for(i = 0; i < LENGTH; i++) \
{printf(#ARRAY "[%d] = %d\n", i, ARRAY[i]);} \
}
#define PRINTFLTARRAY(ARRAY, LENGTH) \
{ \
int i; \
for(i = 0; i < LENGTH; i++) \
{printf(#ARRAY "[%d] = %f\n", i, ARRAY[i]);} \
}
#define PRINTDBLARRAY(ARRAY, LENGTH) \
{ \
int i; \
for(i = 0; i < LENGTH; i++) \
{printf(#ARRAY "[%d] = %g\n", i, ARRAY[i]);} \
}
#define PASTE(FRONT, BACK) FRONT ## BACK // names generator
// TEMP scope is limited to this block:
#define SWAP(T, X, Y) {T TEMP = (X); (X) = (Y); (Y) = TEMP;}
#define EXPAND(...) EXPAND_(__VA_ARGS__) // expand macro
#define EXPAND_(...) # __VA_ARGS__
int main()
{
int PASTE(i, 1), PASTE(i, 2);
i1 = i2 = 0;
IPRINT(PASTE(i, 1));
IPRINT(PASTE(i, 2));
IPRINT(i1);
IPRINT(i2);
IPRINT(MAX(i1++, i2++)); // (i1++) > (i2++) ? (i1++) : (i2++)
// MAX() prints i2, then executes i2++
SPRINTLN(EXPAND(MAX(i1++, i2++)));
IPRINT(i1); // i1++ evaluated once
IPRINT(i2); // i2++ evaluated twice
float PASTE(f, 1), PASTE(f, 2);
f1 = f2 = 0.F;
FPRINT(PASTE(f, 1));
FPRINT(PASTE(f, 2));
FPRINT(f1);
FPRINT(f2);
FPRINT(MAX(++f1, f2++)); // (++f1++) > (f2++) ? (++f1) : (f2++)
// MAX() prints f1 after ++f1
SPRINTLN(EXPAND(MAX(++f1, f2++)));
DPRINT(f1); // ++f1 evaluated twice
DPRINT(f2); // f2++ evaluated once
double x = 2.0;
DPRINT(x);
DPRINT(SQUARE(x+1));
SPRINTLN(EXPAND(SQUARE(x+1)));
char s[] = "Hello, ";
SPRINT(s);
PRINTLN(world!);
int ints[] = {i1, i2};
PRINTINTARRAY(ints, 2);
IPRINT(i1);
IPRINT(i2);
SWAP(int, ints[0], ints[1])
SPRINT2LN(EXPAND(SWAP(int, ints[0], ints[1])));
PRINTINTARRAY(ints, 2);
IPRINT(i1);
IPRINT(i2);
float flt[] = {f1, f2};
PRINTFLTARRAY(flt, 2);
FPRINT(f1);
FPRINT(f2);
SWAP(float, flt[0], flt[1])
SPRINT2LN(EXPAND(SWAP(float, flt[0], flt[1])));
PRINTDBLARRAY(flt, 2);
DPRINT(f1);
DPRINT(f2);
return 0;
}
/*
gcc macros.c -o macros
./macros
PASTE(i, 1) = 0
PASTE(i, 2) = 0
i1 = 0
i2 = 0
MAX(i1++, i2++) = 1
EXPAND(MAX(i1++, i2++)) = ((i1++) > (i2++) ? (i1++) : (i2++))
i1 = 1
i2 = 2
PASTE(f, 1) = 0.000000
PASTE(f, 2) = 0.000000
f1 = 0.000000
f2 = 0.000000
MAX(++f1, f2++) = 2.000000
EXPAND(MAX(++f1, f2++)) = ((++f1) > (f2++) ? (++f1) : (f2++))
f1 = 2
f2 = 1
x = 2
SQUARE(x+1) = 9
EXPAND(SQUARE(x+1)) = ((x+1) * (x+1))
s = Hello, world!
ints[0] = 1
ints[1] = 2
i1 = 1
i2 = 2
EXPAND(SWAP(int, ints[0], ints[1])) =
{int TEMP = (ints[0]); (ints[0]) = (ints[1]); (ints[1]) = TEMP;}
ints[0] = 2
ints[1] = 1
i1 = 1
i2 = 2
flt[0] = 2.000000
flt[1] = 1.000000
f1 = 2.000000
f2 = 1.000000
EXPAND(SWAP(float, flt[0], flt[1])) =
{float TEMP = (flt[0]); (flt[0]) = (flt[1]); (flt[1]) = TEMP;}
flt[0] = 1
flt[1] = 2
f1 = 2
f2 = 1
*/