3.10.4. Duplication of Side Effects. Red Hat ENTERPRISE LINUX 4 - USING BINUTILS, ENTERPRISE LINUX 4 - DEVELOPER TOOLS GUIDE
إعلان
إعلان
32 Chapter 3. Macros
3.10.3. 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) \
{ 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 logical line, so that it resembles the way such 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. However, since it looks like a function call, it minimizes confusion if you can use it like a function call, writing a semicolon afterward, as in SKIP_SPACES (p, lim);
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 { 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. The loop executes exactly once; most compilers generate no extra code for it.
تنزيل
إعلان