The C Preprocessor - Swallow Semicolon

Node: Swallow Semicolon Next: Side Effects Prev: Macro Parentheses Up: Macro Pitfalls

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; }}}

Here 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 you can use it like a function call, writing a semicolon afterward, as in `SKIP_SPACES (p, lim);'

But this can cause trouble before `else' statements, because the semicolon is actually a null statement. Suppose you write

	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. Here is how:

	#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

	do {...} while (0);

which is one statement.


Next: Side Effects Up: Macro Pitfalls