cpp: Swallowing the Semicolon
1
1 3.10.3 Swallowing the Semicolon
1 -------------------------------
1
1 Often it is desirable to define a macro that expands into a compound
1 statement. Consider, for example, the following macro, that advances a
1 pointer (the argument 'p' says where to find it) across whitespace
1 characters:
1
1 #define SKIP_SPACES(p, limit) \
1 { char *lim = (limit); \
1 while (p < lim) { \
1 if (*p++ != ' ') { \
1 p--; break; }}}
1
1 Here backslash-newline is used to split the macro definition, which must
1 be a single logical line, so that it resembles the way such code would
1 be laid out if not part of a macro definition.
1
1 A call to this macro might be 'SKIP_SPACES (p, lim)'. Strictly
1 speaking, the call expands to a compound statement, which is a complete
1 statement with no need for a semicolon to end it. However, since it
1 looks like a function call, it minimizes confusion if you can use it
1 like a function call, writing a semicolon afterward, as in 'SKIP_SPACES
1 (p, lim);'
1
1 This can cause trouble before 'else' statements, because the
1 semicolon is actually a null statement. Suppose you write
1
1 if (*p != 0)
1 SKIP_SPACES (p, lim);
1 else ...
1
1 The presence of two statements--the compound statement and a null
1 statement--in between the 'if' condition and the 'else' makes invalid C
1 code.
1
1 The definition of the macro 'SKIP_SPACES' can be altered to solve
1 this problem, using a 'do ... while' statement. Here is how:
1
1 #define SKIP_SPACES(p, limit) \
1 do { char *lim = (limit); \
1 while (p < lim) { \
1 if (*p++ != ' ') { \
1 p--; break; }}} \
1 while (0)
1
1 Now 'SKIP_SPACES (p, lim);' expands into
1
1 do {...} while (0);
1
1 which is one statement. The loop executes exactly once; most compilers
1 generate no extra code for it.
1