I use names identical to function names for expression macros (macros that return values). In general, I use all upper case names for block macros (macros that have multiple statements). The intent is that, for efficiency, we will freely interchange expression macros and functions, so there should be no distinction between the two. However, block macros may need special treatment, and the user, by looking at the all upper case name, will conclude that something special is going on.
Block macros should be enclosed by a do { ... } while(0) construct. The reason is simple - we want the user of the macro to be forced to put a ; after the use of the macro. Specifically, if we defined the SWAP macro as:
#define SWAP(_x, _y) \
{ \
int _t = (_x); \
(_x) = (_y); \
(_y) = _t; \
}
In this case both SWAP(s, t) and SWAP(s,t); will be accepted by the compiler. However, if we enclosed the definition with a do {...} while(0), only the second case would compile.
Here are some equivalences between standard C constructs and their macro equivalents
v = expr; (void)((v) = expr)
st1; (st1), (st2)
st2;
if( pred ) { (pred)?(st1):(st2)
st1;
}
else {
st2;
}
return (expr); (expr)
In an expression macro, local variables are best handled by having the macro take an extra parameter that is used as a scratch value.
#define swap(_x, _y, _t) \
( (_t) = (_x), \
(_x) = (_y), \
(_y) = (_t) )
In a block structured macro, of course, one can declare a variable with local scope. Try and pick a name that will not be confused with one of the parameters. By convention, I prefix all local scope variables defined in a block macro with an _. Thus
#define SWAP(_x, _y) \
do { \
int _t = (_x); \
(_x) = (_y); \
(_y) = _t; \
} while(0)
Assume that we local scope variables t instead of _t. In that case, if the macro was invoked as SWAP(s, t), it would incorrectly expand to:
do {
int t = s;
s = t;
t = s;
} while(0)
Consider the following example:
Foo
head_foo_list(
FooList * p_list
)
{
if( *p_list ) {
return value_foo_list(*p_list);
}
else {
return 0;
}
}
Using the rules above, we can construct an expression macro as:
#define head_foo_list(_p_list) \
( (*p_list)?\
value_foo_list(*p_list):\
(0))