我想调用循环中的多行宏来打破/继续它。
如果我在多行宏定义中使用“do {...} while(0)”,则break / continue仅对“do {...} while(0)”有效,而不是调用的循环这个宏。所以我考虑在多宏定义中使用“if(1){...}”。
#define EXIT_CIRCULATION() \
if(1){ \
break; \
}
void func(){
while(1){
...
EXIT_CIRCULATION();
...
}
}
但我怀疑在宏定义中使用“if(1){...}”是一种好方法,因为我在互联网上找不到任何例子。
谢谢!
答案 0 :(得分:10)
如果您编写类似
的代码 if (somecondition)
EXIT_CIRCULATION();
else
break;
然后宏的扩展将不会像你直觉所期望的那样。 else
适用于您的if (1)
,永远不会发生。
答案 1 :(得分:2)
这个技巧背后的整个想法是找到一种方法来创建一个多行(即复合)语句,该语句还包含一个终止;
作为其组成部分。这将使您有机会在宏调用后使用;
,而不会无意中引入空语句。
{ ... }
中的普通复合语句不起作用,因为它不会以;
结尾。 C / C ++中唯一以;
结尾的多行语句是do/while
。 C / C ++语法中没有其他语句可以满足此要求。 (这是一个不准确的声明,见下面的“P.S.”)
在所有其他情况下(包括您的if (1) {...}
),宏调用后的;
将被视为其他独立的独立空语句。这将使您在宏调用后编写;
时无法在需要完全一个语句的上下文中使用它(如if-else
的真分支或{{{{ 1}}循环)。
例如,如果您定义
do/while
然后此代码将无法编译
#define A() if (1) {}
因为它将替换为
do
A();
while (1);
这实际上是do
if (1) {}; /* <- two statements, not one */
while (1);
和do
之间的两个语句。在while
和do
之间指定两个语句而不将它们包装到while
中是语法错误。
<强> P.S。更正:我上面提到的关于{}
只是 可行变体的说法不正确。在@Michael Burr的回答中,您可以看到另一个合适的变体,它使用do/while
技巧用于相同的目的。但是,主要原则保持不变。
答案 2 :(得分:2)
这是一个我认为可以安全地做你想要的宏:
#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 == %d\n", i);
return 0;
}
输出:
working...
working...
working...
working...
working...
done.
i == 5