151

Possible Duplicates:
Do-While and if-else statements in C/C++ macros
do { ... } while (0) — what is it good for?

I'm reading the linux kernel and I found many macros like this:

#define INIT_LIST_HEAD(ptr) do { \
 (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

Why do they use this rather than define it simply in a {}?

John Kugelman
364k70 gold badges555 silver badges600 bronze badges
asked May 29, 2009 at 0:05
0

2 Answers 2

162

You can follow it with a semicolon and make it look and act more like a function. It also works with if/else clauses properly then.

Without the while(0), your code above would not work with

if (doit) 
 INIT_LIST_HEAD(x);
 else 
 displayError(x);

since the semicolon after the macro would "eat" the else clause, and the above wouldn't even compile.

answered May 29, 2009 at 0:09
Sign up to request clarification or add additional context in comments.

5 Comments

But the OP's question stands. Why not just { (ptr)->next ... } instead of do { (ptr)->next ... } while (0);?
arno explained that. It would expand to "{ (ptr)->next ... };" thus, a statement followed by a second statement. If syntax however is "if ( expression ) statement else statement" . The else would not be associated with any if, since you would have written "if ( expression ) statement statement" (one "{ ... }" and one ";" statement).
As Amo said, it's a clever trick that allows a macro to be a C statement that must end with a semicolon. It makes the macro act exactly like a function call, so far as statement construction and termination (with ';') is concerned.
Note, however, that in this case it's all completely unnecessary, as the body of the macro could be written much more cleanly as: (ptr)->next=(ptr)->prev=(ptr).
@JoshK the loop will be executed only once because while(0) is a false condition. However, an optimizing compiler will get ride of the do {stat}while(0) & replace with only stat because anyway, it's happening only once.
48

It allows you to group several statements into one macro.

Assume you did something like:

if (foo) 
 INIT_LIST_HEAD(bar);

If the macro was defined without the encapsulating do { ... } while (0);, the above code would expand to

if (foo)
 (bar)->next = (bar);
 (bar)->prev = (bar);

This is clearly not what was intended, as only the first statement will be executed if foo holds. The second statement would be executed regardless of whether foo holds.

Edit: Further explanation at http://c-faq.com/cpp/multistmt.html and http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon

answered May 29, 2009 at 0:11

3 Comments

This doesn't explain the do .. while(0) part of the macro, just the use of {} braces.
do {} while (0) part is explained in the post this one is dup of.
SPWorley, adobriyan: Actually, it looks like this post's author added links explaining the do {} while (0).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.