行宏: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'版本的整个想法不包括这个最后的决定;
进入宏观(因为我上面解释的原因)。