10.4. Caveats for macros

Macros can be miss-used and it's hard to catch the bugs because the macro no longer exists when the code gets to the compiler. The most error is the macro argument with side effect. Take the this small example:

Example 10-2. max_macro.c

#define MAX(a, b) (a > b ? a : b)

int
main()
{
  int cows = 10, sheep = 12;

  printf("we have %d of our most common animal\n", MAX(cows, sheep));

  return 0;
}
     
We compile and execute this code and get:
ciaran@pooh:~/book$ ./a.out
we have 12 of our most common animal
ciaran@pooh:~/book$
    
Yup, everything looks good. Try this next example:

Example 10-3. max_macro_problem.c

#define MAX(a, b) (a > b ? a : b)

int
main()
{
  int cows = 10, sheep = 12;

  printf("We have %d of our most common animal\n", MAX(cows, sheep));

  printf("Hang on, we just bought another one.\n");
  printf("Now we have %d.\n", MAX(cows, ++sheep));

  return 0;
}
     
Can you see what's going to happen?
ciaran@pooh:~/book$ ./a.out
We have 12 of our most common animal
Hang on, we just bought another one.
Now we have 14.
ciaran@pooh:~/book$
    
When the text substitution occurs there will be two instances of ++sheep. Another more sinister way for this bug may manifest itself is when you pass use a function as an argument to a macro. If the function modifies a global or static variable then this modification may occur multiple times. These bugs can be very hard to find, the code is perfectly valid so the compiler has nothing to complain about, the bug will only be noticed at run time and wont occur every time the macro is called, only when it is called with an argument that has a side effect.