20

可能重复:
为什么在 C/C++ 宏中有时会出现无意义的 do/while 和 if/else 语句?

我遇到了如下代码:

#define ev_io_init(ev,cb,fd,events) \
do { \
  ev_init ((ev), (cb)); \
  ev_io_set ((ev),(fd),(events)); \
} while (0)

我想知道作者为什么在do { } while (0)这里使用。这有什么区别吗?

#define ev_io_init(ev,cb,fd,events) { \
  ev_init ((ev), (cb)); \
  ev_io_set ((ev),(fd),(events)); \
}

顺便说一句:代码来自 libev,ev_local.h

4

3 回答 3

31

考虑if( something ) function1(); else function2();

iffunction1()实际上是一个宏,只是 using{ }要求您在使用时省略分号,但do { } while(0)允许您使用与实际函数完全相同的语法。

(根本不使用任何类型的块构造只会生成完全损坏的代码,natch)

于 2012-02-29T08:50:19.590 回答
20

用循环封闭代码允许预处理器指令执行多个语句而不会“破坏” if-else-constructs。考虑以下:

#define DO_SOMETHING() a();b();c();

void foo()
{
    // This is ok...
    DO_SOMETHING();
}

void bar()
{
    // ...whereas this would trigger an error.
    if (condition)
       DO_SOMETHING();
    else
       blah();
}

第二个示例破坏了 if-else-construct,因为三个语句后跟一个else子句。为了允许它正确替换,中的说明DO_SOMETHING应该用do { ... } while(0).

于 2012-02-29T08:49:41.357 回答
12

Ado{}while(0)允许你跳出循环:

do{
   expr1;
   foo();
   if ( cond )
      break;
   expr2;
   goo(); 
} while (0);

它与简单块{...}相同,只是您可以在需要时使用break语句中断执行。你不能在一个简单的代码块中做到这一点,除非你有多个检查,这会变得很麻烦。由于条件,它仍然执行一次while(0)

于 2012-02-29T08:46:26.253 回答