C多行宏:do / while(0)vs scope block

时间:2009-07-01 04:06:36

标签: c macros multiline

  

可能重复:
  What’s the use of do while(0) when we define a macro?
  Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?
  do { … } while (0) what is it good for?

我见过一些包含在do / while(0)循环中的多行C宏,如:

#define FOO \
  do { \
    do_stuff_here \
    do_more_stuff \
  } while (0)

与使用基本块相反,编写代码有什么好处(如果有的话):

#define FOO \
  { \
    do_stuff_here \
    do_more_stuff \
  }

1 个答案:

答案 0 :(得分:248)

http://bytes.com/groups/c/219859-do-while-0-macro-substitutions

Andrey Tarasevich:

使用'do / while'版本的整个想法是创建一个宏 扩展为常规语句,而不是复合语句。这是 为了使函数式宏使用而完成 在所有情境中使用普通函数。

考虑以下代码草图

if (<condition>)
  foo(a);
else
  bar(a);

其中'foo'和'bar'是普通函数。现在想象一下你 喜欢将函数'foo'替换为上述性质的宏

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);

现在,如果您的宏是按照第二种方法定义的 (只是'{'和'}')代码将不再编译,因为'true' 'if'的分支现在由复合语句表示。当你 放一个';'在这个复合语句之后,你完成了整个'if' 声明,因此孤立'else'分支(因此编译错误)。

解决此问题的一种方法是记住不要放';'后 宏“调用”

if (<condition>)
  CALL_FUNCS(a)
else
  bar(a);

这将按预期编译和工作,但这不统一。该 更优雅的解决方案是确保宏扩展为常规 声明,而不是复合词。实现这一目标的一种方法是定义 宏如下

#define CALL_FUNCS(x) \
do { \
  func1(x); \
  func2(x); \
  func3(x); \
} while (0)

现在这段代码

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);

将编译没有任何问题。

然而,请注意我的定义之间的微小但重要的区别 CALL_FUNCS和您邮件中的第一个版本。我没有放一个 ;之后的} while (0)。将;放在该定义的末尾 会立即打败使用'do / while'和make的整个过程 那个宏几乎等同于复合语句版本。

我不知道为什么你原来引用的代码的作者 消息将此;放在while (0)之后。在这种形式中,两种变体都是 当量。使用'do / while'版本背后的整个想法不是 将此最终;包含在宏中(出于我解释的原因) 上文)。