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

kra*_*aya 173 c macros multiline

可能的重复:
当我们定义一个宏时,do(0)有什么用?
为什么在C/C++宏中有时会出现无意义的do/while和if/else语句?
做{...}而(0)有什么好处?

我已经看到一些包含在do/while(0)循环中的多行C宏,如:

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

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

#define FOO \
  { \
    do_stuff_here \
    do_more_stuff \
  }

cas*_*key 259

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

安德烈塔拉谢维奇:

使用'do/while'版本的整个想法是创建一个宏,它将扩展为常规语句,而不是复合语句.这样做是为了在所有上下文中使用普通函数使函数式宏统一使用.

请考虑以下代码草图

if (<condition>)
  foo(a);
else
  bar(a);
Run Code Online (Sandbox Code Playgroud)

其中'foo'和'bar'是普通函数.现在假设您想用上述性质的宏替换函数'foo'

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);
Run Code Online (Sandbox Code Playgroud)

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

解决这个问题的一种方法是记住不要放';' 在宏"调​​用"之后

if (<condition>)
  CALL_FUNCS(a)
else
  bar(a);
Run Code Online (Sandbox Code Playgroud)

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

#define CALL_FUNCS(x) \
do { \
  func1(x); \
  func2(x); \
  func3(x); \
} while (0)
Run Code Online (Sandbox Code Playgroud)

现在这段代码

if (<condition>)
  CALL_FUNCS(a);
else
  bar(a);
Run Code Online (Sandbox Code Playgroud)

将编译没有任何问题.

但是,请注意我的定义{与消息中的第一个版本之间的小但重要的区别.我没有把一 }CALL_FUNCS.把一个;在该定义的结束将立即打败使用的整个点"做/同时",使宏观几乎相当于复合语句的版本.

我不知道为什么您在原始邮件中引用的代码的作者将此放在} while (0)后面;.在这种形式中,两种变体是等同的.使用'do/while'版本背后的整个想法不是将此最终内容;包含在宏中(出于我上面解释的原因).

  • 原帖是由我在`comp.lang.c`中创建的.`bytes.com`显然"挪用"了`comp.lang.c`的内容而没有对源进行任何引用. (46认同)

归档时间:

查看次数:

100321 次

最近记录:

6 年,2 月 前