C多行宏:do/while(0) vs scope block [重复]
Posted
技术标签:
【中文标题】C多行宏:do/while(0) vs scope block [重复]【英文标题】:C multi-line macro: do/while(0) vs scope block [duplicate] 【发布时间】:2010-11-07 05:21:00 【问题描述】:可能的重复: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_stuff_here \ 做更多的东西\ 而 (0)与使用基本块相比,以这种方式编写代码有哪些好处(如果有的话):
#define FOO \ \ do_stuff_here \ 做更多的东西\【问题讨论】:
重复:***.com/questions/923822 和 ***.com/questions/154136 和 ***.com/questions/257418 实际上还有另一种方法可以让事情变得正确。 (...) 可以做与 while(0) 相同的事情。参考:bruceblinn.com/linuxinfo/DoWhile.html @wuxb:(...)
构造是 GCC 扩展,不受 ISO 标准 C 支持。
这也是 CERT 推荐的方法:wiki.sei.cmu.edu/confluence/display/c/…
【参考方案1】:
Andrey Tarasevich 提供以下解释:
-
On Google Groups
On bytes.com
[对格式进行了细微更改。在方括号中添加了括号注释[]
]。
使用“do/while”版本的整个想法是制作一个宏,它将 扩展为常规语句,而不是复合语句。这是 这样做是为了使函数式宏的使用与 在所有上下文中使用普通函数。
考虑以下代码草图:
if (<condition>) foo(a); else bar(a);
其中
foo
和bar
是普通函数。现在想象你会 喜欢用上述性质的宏[命名为CALL_FUNCS
]替换函数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”的全部意义,并使 该宏几乎等同于复合语句版本。我不知道为什么你在原文中引用的代码的作者 消息把这个
;
放在while (0)
之后。在这种形式下,两种变体都是 相等的。使用“do/while”版本背后的整个想法不是 将这个最后的;
包含在宏中(出于我解释的原因 以上)。
【讨论】:
原帖是我在comp.lang.c
发的。 bytes.com
显然“挪用”了comp.lang.c
的内容,而没有提及任何来源。以上是关于C多行宏:do/while(0) vs scope block [重复]的主要内容,如果未能解决你的问题,请参考以下文章
C语言do...while语句的妙用(包裹宏替换多句代码)(代替go to语法)(隔绝外部变量)
在 C 宏中,是不是应该更喜欢 do ... while(0,0) 而不是 do ... while(0)?