C多行宏:do / while(0)与范围块[重复]

问题描述 投票:172回答:1

可能的重复项: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?

我已经看到了一些多行C宏,它们包裹在do / while(0)循环中,例如:

#define FOO \做{\do_stuff_here \do_more_stuff \}而(0)

以这种方式编写代码(与使用基本块相比,有什么好处(如果有):

#define FOO \{\do_stuff_here \do_more_stuff \}
c macros multiline
1个回答
256
投票

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

安德烈·塔拉瑟维奇:

使用'do / while'版本的整个想法是创建一个宏扩展为常规语句,而不是复合语句。这是为了使函数样式宏与在所有情况下都使用普通功能。

请考虑以下代码草图

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

其中'foo'和'bar'是普通函数。现在想象你会想要用上述性质的宏替换功能'foo'

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

现在,如果您的宏是根据第二种方法定义的,(仅{})该代码将不再编译,因为'true'现在,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'的意义,并使该宏几乎等同于复合语句版本。

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

© www.soinside.com 2019 - 2024. All rights reserved.