我正在阅读linux内核,我发现了很多像这样的宏:
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
为什么他们使用这个而不是简单地在{}?
中定义它答案 0 :(得分:135)
您可以使用分号跟随它,使其看起来更像一个函数。 它也适用于if / else子句。
如果没有while(0),上面的代码将不适用于
if (doit)
INIT_LIST_HEAD(x);
else
displayError(x);
因为宏之后的分号会“吃掉”else子句,而上面的内容甚至都不会编译。
答案 1 :(得分:42)
它允许您将多个语句组合成一个宏。
假设你做了类似的事情:
if (foo)
INIT_LIST_HEAD(bar);
如果在没有封装do {...} while(0);的情况下定义宏,则上面的代码将扩展为
if (foo)
(bar)->next = (bar);
(bar)->prev = (bar);
这显然不是预期的,因为如果foo成立,只会执行第一个语句。无论foo是否成立,第二个语句都将被执行。
修改:http://c-faq.com/cpp/multistmt.html和http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon
的进一步说明