行宏:do / while(0)vs范围块

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

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

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

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

#define FOO 
  { 
    do_stuff_here 
    do_more_stuff 
  }

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

安德烈Tarasevich:

使用'do / while'版本的整个想法是制作一个宏,它将扩展成一个正则表达式,而不是一个复合语句。 这样做是为了在所有上下文中使用普通函数来使用函数式宏。

考虑下面的代码草图

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

'foo'和'bar'是普通函数。 现在想象一下,你想用上述性质的宏来替换函数'foo'

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

现在,如果你的宏是按照第二种方法定义的(只是'{'和'}'),代码将不再编译,因为'if'的'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'版本的整个想法不包括这个最后的决定; 进入宏观(因为我上面解释的原因)。

链接地址: http://www.djcxy.com/p/36381.html

上一篇: line macro: do/while(0) vs scope block

下一篇: C Bitwise Operators Example