do{…}while(0) 的秒用

在linux内核代码中,有这样的宏定义:
#define DUMP_WRITE(addr,nr) do{ memcpy(bufp,addr,nr); bufg+=nr; }while(0)

这个宏定义意味着引用这个宏操作时会执行循环体一次,但为什么要定义成这样的怪形式呢?

我们看看其他几种形式的宏定义:
#define DUMP_WRITE(addr,nr)  memcpy(bufp,addr,nr);  bufp+=nr;

这种宏定义行不行?

我们把这个宏放到一个语境中:
if (addr)

    DUMP_WRITE(addr,nr);

else

    do_something_else();

结果发现编译会出错,为什么?

把宏展开,上述语句块变为:
if (addr)

    memcpy(bufp,addr,nr); bufp+=nr;

else

    do_something_else();

这样就会在if-else语句之间加了一条语句bufp+=nr;形成类似于 if-dosomething-else 的语句。这样else将无法找到与之匹配的 if,所以编译器会报错。

换种引用形式:
if(!addr)

    do_something_else();

else

    DUMP_WRITE(addr,nr);

这样虽然编译能通过,但是问题会更严重,因为bufp+=nr; 会始终被执行。

到这里,我们可能马上会想到在宏定义中加一个大括号:

#define DUMP_WRITE(addr,nr)  {memcpy(bufp,addr,nr);  bufp+=nr;}

这样能行吗?我们放到语境中测试下:

if (addr)

    DUMP_WRITE(addr,nr);

else

    do_something_else();

依然编译出错,为什么呢?

将宏展开之后为:

if (addr)

    {memcpy(bufp,addr,nr);  bufp+=nr;};

else

    do_something_else();

这里在if-else语句中插入了一条空语句:if-空语句-else,同样的编译器也不能为 else 找到与之匹配的 if 语句。所以依然会编译报错。

而使用下面这种格式的宏定义,则完全没问题。

#define DUMP_WRITE(addr,nr) do{ memcpy(bufp,addr,nr); bufg+=nr; }while(0)

posted @ 2011-02-18 11:49  莫回头  阅读(297)  评论(0编辑  收藏  举报