Contents|Index|Previous|Next

Swallowing the Semicolon

Often it is desirable to define a macro that expands into a compound statement. Consider, for example, the following macro, that advances a pointer (the argument, p, says where to find it) across whitespace characters.

    #define SKIP_SPACES (p, limit) \
    { register char *lim = (limit); \
       while (p != lim) { \
          if (*p++ != ’ ’) { \
                p--; break; }}}

Note:
Backslash-Newline is used to split the macro definition, which must be a single line, so that it resembles the way such C code would be laid out if not part of a macro definition.

A call to this macro might be SKIP_SPACES (p, lim). Strictly speaking, the call expands to a compound statement, which is a complete statement with no need for a semicolon to end it. But it looks like a function call. So it minimizes confusion if to use it like a function call, writing a semicolon afterward, as in the following example.

    SKIP_SPACES (p, lim);

But this can cause trouble before else statements, because the semicolon is actually a null statement. Suppose you have the following input.

    if (*p != 0)
       SKIP_SPACES (p, lim);
    else. . .

The presence of two statements—the compound statement and a null statement—in between the if condition and the else makes invalid C code. The definition of the macro SKIP_SPACES can be altered to solve this problem, using a do...while statement. Use the following input as an example.

    #define SKIP_SPACES (p, limit) \
    do { register char *lim = (limit); \
          while (p != lim) { \
                if (*p++ != ’ ’) { \
                   p--; break; }}} \
    while (0)

Now SKIP_SPACES (p, lim); expands into one output statement as the following example shows.

    do { : : :
    } while (0);