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 {}?
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 {}?
My guess would be something to do with portability across platforms and compilers.
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.
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