...
Inline functions are, in general, more suitable for this task. (See recommendation PRE00-C. Prefer inline or static functions to function-like macros.) Occasionally, however, they are not feasible (when macros are expected to operate on variables of different types, for example).
When multiple statements are used in a macro, they should be bound together in a do-while loop syntactically, so the macro can appear safely inside if clauses or other places that expect a single statement or a statement block. (Alternatively, when an if
, for
, or while
statement uses braces even for a single body statement, then multiple statements in a macro will expand correctly even without a do-while loop. See recommendation EXP19-C. Use braces for the body of an if, for, or while statement.
...
Code Block |
---|
|
/*
* Swaps two values.
* Requires tmp variable to be defined.
*/
#define SWAP(x, y) \
tmp = x; \
x = y; \
y = tmp
|
This macro will expand correctly in a normal sequence of statements, but not as the then
- clause in an if
statement:
Code Block |
---|
|
int x, y, z, tmp;
if (z == 0)
SWAP( x, y);
|
This It will expand to the following, which is certainly not what the programmer intended:
Code Block |
---|
|
int x, y, z, tmp;
if (z == 0)
tmp = x;
x = y;
y = tmp;
|
This is certainly not what the programmer intended.
Noncompliant Code Example
...
Code Block |
---|
|
/*
* Swaps two values.
* Requires tmp variable to be defined.
*/
#define SWAP(x,y) { tmp=x; x=y; y=tmp; }
|
This macro fails to expand correctly in some case, such as the following example, which is meant to be an if
- statement with two branches:
Code Block |
---|
|
if (x > y)
SWAP(x,y); /* Branch 1 */
else
do_something(); /* Branch 2 */
|
Following macro expansion, however, this code is interpreted as an if
- statement with only one branch:
Code Block |
---|
|
if (x > y) { /* Single-branch if-statement!!! */
tmp = x; /* The one and only branch consists */
x = y; /* of the block. */
y = tmp;
}
; /* empty statement */
else /* ERROR!!! "parse error before else" */
do_something();
|
The problem is the semi-colon ';' semicolon (;
) following the block.
Compliant Solution
...
Code Block |
---|
|
/*
* Swaps two values.
* Requires tmp variable to be defined.
*/
#define SWAP(x, y) \
do { \
tmp = x; \
x = y; \
y = tmp; } \
while (0)
|
...