C多行宏问题:为什么不使用if(1){..}而不是do{..}while(0)在多行宏定义中
C multi-line macro issue: why not use if(1){...} instead of do{...}while(0) in multi-line macro definition
我想调用循环中的多行宏来中断/继续它。
如果我使用"do"{...}while(0)"在多行宏定义中,中断/继续仅对"do"有效{...}while(0)",而不是调用这个宏的循环。所以我考虑在多宏定义中使用"if(1){…}"。
#define EXIT_CIRCULATION()
if(1){
break;
}
void func(){
while(1){
...
EXIT_CIRCULATION();
...
}
}
但我怀疑在宏观定义中使用"if(1){…}"是否是一种好方法,因为我在互联网上找不到任何例子。
谢谢!
如果您编写类似的代码
if (somecondition)
EXIT_CIRCULATION();
else
break;
那么宏的扩展就不会像你直观地预期的那样。else
将适用于您的if (1)
,并且永远不会发生。
这个技巧背后的全部思想是找到一种方法来创建一个多行(即复合)语句,该语句还包含一个终止;
作为其组成部分。这将使您有机会在宏调用后使用;
,而不会无意中引入空语句。
{ ... }
中的普通复合语句不起作用,因为它没有以;
结尾。C/C++中唯一以;
结尾的多行语句是do/while
。C/C++语法中没有其他语句可以满足这一要求。(这是一个不准确的说法,请参阅下面我的"P.S.")
在所有其他情况下(包括if (1) {...}
),宏调用后的;
将被视为额外的独立空语句。这将使您无法在宏调用后编写;
,因为它用于需要恰好一个语句的上下文(如if-else
的真实分支或do/while
循环的主体)。
例如,如果定义
#define A() if (1) {}
则该代码不会编译
do
A();
while (1);
因为它将被取代
do
if (1) {}; /* <- two statements, not one */
while (1);
这实际上是CCD_ 14和CCD_。在do
和while
之间指定两个语句而不将它们包装到{}
中是语法错误。
p.S.更正:我上面关于do/while
是唯一的可行变体的说法是不正确的。在@Michael Burr的回答中,你可以看到另一个合适的变体,即出于同样的目的使用else ((void) 0)
技巧。然而,主要原则保持不变。
这里有一个宏,我相信它可以安全地执行您想要的操作:
#define EXIT_CIRCULATION()
if (1) {
/* some statements */
break;
}
else
do {} while (0)
这里的if
与else
匹配,这意味着该宏在另一个if
中使用是安全的,并且由于else
子句是一个无所事事的do
/while
语句,它提供了与在do
/while
中包装多行宏类似的属性。例如,宏将需要以分号结尾,就像它是一个正常的语句一样;忘记分号会导致语法错误。它在另一个if
或else
子句中起到了很好的作用。
对你来说(我认为)最重要的是,break
语句不会被宏吞噬——它会打破宏使用的循环。
这是不是一个好主意完全是另一回事。许多程序员不喜欢流控制语句隐藏在宏中(除非控制流完全在宏单元中)。
它在这里发挥作用:
#include<stdio.h>
#include<stdlib.h>
#define EXIT_CIRCULATION()
if (1) {
puts("done.");
break;
}
else
do {} while (0)
int main()
{
int i = 0;
for (i = 0; i < 10; ++i) {
if (i > 4)
EXIT_CIRCULATION();
else
puts("working...");
}
printf("i == %dn", i);
return 0;
}
输出:
working...
working...
working...
working...
working...
done.
i == 5
- C++宏定义和取消定义
- 根据 c++ 标准在该宏定义中推送/弹出宏时的行为是什么
- VS2017 #error: : snprintf 的宏定义与标准库函数声明冲突
- 宏定义不正确没有错误
- Visual Studio:snprintf 冲突的宏定义
- 宏定义中的预处理器令牌两边有两个双引号
- CMake 添加和删除宏定义以编译共享库/可执行文件
- 宏C++#定义示例(对象)(::f(s,(对象),arg1,arg2,arg3)
- 根据模板参数选择宏定义
- 使用宏定义打印格式参数
- 组合宏定义以一次获得多个定义 [avr C++]
- 如何在可执行文件中查看宏定义值
- 是否有另一种方法可以在不使用宏定义的情况下进行此操作
- 如何理解宏定义
- 坚持理解以下宏定义
- 发布C++宏定义
- 通过生成文件预处理器宏定义在 c++ 中无法正常工作
- 将预处理器宏定义为宏定义线
- GCC是否支持宏定义中的多行原始字符串文字
- C多行宏问题:为什么不使用if(1){..}而不是do{..}while(0)在多行宏定义中