04-27-07 12:17 AM
djhong@gmail.com wrote On 04/26/07 13:47,:
> (Since queue.h is not a part of standard C, I'd lke to ask here)
>
> For example, BSD implementation of sys/queue.h has following weird
> macros:
> I can't understand why "do{}while(0)" is used... Removing
> "do{}while(0)" from these macros should be ok. Right?
>
>
> #define SLIST_INIT(head) do { \
> SLIST_FIRST((head)) = NULL; \
> } while (0)
>
> #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
> SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
> SLIST_NEXT((slistelm), field) = (elm); \
> } while (0)
>
> #define SLIST_INSERT_HEAD(head, elm, field) do { \
> SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
> SLIST_FIRST((head)) = (elm); \
> } while (0)
>
> #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
(You seem to be missing some backslashes.)
No reason I can see for do{}while(0) on the first
one, but for the next two it makes sense. Maybe the
first has do{}while(0) just for consistency's sake, or
maybe an earlier version of the first macro had more
than one statement.
The reason for the do{}while(0) dodge in multi-
statement macro expansions is to make them work right
in contexts where just one statement is allowed. For
example, try this simple macro:
#define MESSAGE(msg) { \
fputs (msg, stdout);
fputs (msg, stderr);
}
Easy enough, right? MESSAGE("Hello, world!\n") writes
the message to two output streams. But let's try it
in this context:
if (firstGreetingOfTheDay)
MESSAGE("Hello, world!\n");
else
MESSAGE("Hi again.\n");
(If you don't see the problem, feed it to a compiler
and see what it says.)
Now, you could "fix" this with documentation: "When
you use the MESSAGE macro, never put a semicolon at
the end." But that's not a really wonderful solution
because it requires the programmer to be aware that this
"function-like macro" is really a macro and not an actual
function, and requires that it be coded with a different
style than pretty much everything else. (And it will
probably raise merry Hell with automatic code formatters,
too.) The do{}while(0) dodge turns the macro expansion
into a single semicolon-terminated statement, and the
programmer's life gets simpler.
--
Eric.Sosman@sun.com
[ Post a follow-up to this message ]
|