Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

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
bgColor#FFcccc
langc

/*
 * 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
bgColor#FFcccc
langc

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
bgColor#FFcccc
langc

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
bgColor#FFcccc
langc

/*
 * 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
bgColor#FFcccc
langc

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
bgColor#FFcccc
langc

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
bgColor#ccccFF
langc

/*
 * Swaps two values.
 * Requires tmp variable to be defined.
 */
#define SWAP(x, y) \
  do { \
    tmp = x; \
    x = y; \
    y = tmp; } \
  while (0)

...