【问题标题】:Why use do { } while (0) in macro definition? [duplicate]为什么在宏定义中使用 do { } while (0)? [复制]
【发布时间】:2012-03-18 18:03:34
【问题描述】:

可能重复:
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)); \
}

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

【问题讨论】:

    标签: c c-preprocessor libev


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      用循环封闭代码允许预处理器指令执行多个语句而不会“破坏” 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) 括起来。

      【讨论】:

      • 当然,如果你使用这样的裸 if 行,你应该让你的代码中断......
      • @Simon 但是 linux 内核编码风格不建议我们对一个行块使用裸 if else 行吗? kernel.org/doc/Documentation/CodingStyle
      • @CoderSpinoza 显然是这样,如果我要在 linux 内核上工作,那么我会遵循这种风格。在其他地方,我会避免它。
      • 很多 C 代码仓库使用一行 ifs 没有大括号,完全没问题。
      【解决方案3】:

      do{}while(0) 允许您跳出循环:

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

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

      【讨论】:

      • ...可以,但请不要...
      • 它减少了 if-else 的嵌套次数。
      猜你喜欢
      • 2010-10-29
      • 1970-01-01
      • 2016-08-22
      • 2012-03-08
      • 2010-09-20
      • 2012-05-30
      相关资源
      最近更新 更多