为什么在宏定义中使用do {} while(0)?

时间:2012-02-29 08:45:24

标签: c c-preprocessor libev

  

可能重复:
  Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?

我遇到了如下代码:

#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)); \
}

BTW:代码来自libev,ev_local.h

3 个答案:

答案 0 :(得分:23)

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

如果function1()实际上是一个宏,那么仅使用{ }要求您在使用时省略分号,但do { } while(0)允许您使用与真实语法完全相同的语法功能

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

答案 1 :(得分:15)

使用循环封闭代码允许预处理程序指令执行多个语句而不“破坏”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)

答案 2 :(得分:10)

do{}while(0)允许您从循环中断开:

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

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

相关问题