2

我想在循环中调用多行宏来中断/继续它。

如果我在多行宏定义中使用“do{...}while(0)”,break/continue 只对“do {...}while(0)”有影响,而不是调用这个宏的循环。所以我考虑在多宏定义中使用“if(1){...}”。

#define EXIT_CIRCULATION() \
        if(1){ \
           break; \
        }

void func(){
    while(1){
       ...
       EXIT_CIRCULATION();
       ...
    }
}

但我怀疑在宏定义中使用“if(1){...}”是否是一种好方法,因为我在互联网上找不到任何示例。

谢谢!

4

3 回答 3

10

如果您编写类似的代码

 if (somecondition)
    EXIT_CIRCULATION();
 else
    break;

那么你的宏的扩展将不会像你直觉的那样表现。这else将适用于您if (1)并且永远不会发生。

于 2012-11-26T06:35:35.063 回答
2

这个技巧背后的整个想法是找到一种方法来创建一个多行(即复合)语句,该语句还包含一个终止;作为其组成部分。这将使您有机会;在宏调用之后使用,而不会无意中引入空语句。

普通的复合语句 in{ ... }不起作用,因为它不以;. C/C++ 中唯一;do/while. C/C++ 语法中没有其他语句可以满足这个要求。(这是一个不准确的说法,请参阅下面我的“PS”)

在所有其他情况下(包括您的if (1) {...};,宏调用之后将被视为附加的独立独立空语句。当宏调用用于需要一个;语句的上下文(如真正的分支或循环体)中时,这将无法在宏调用之后编写。if-elsedo/while

例如,如果您定义

#define A() if (1) {}

那么这段代码将无法编译

do
  A();
while (1);

因为它将被替换为

do
  if (1) {}; /* <- two statements, not one */
while (1);

这实际上是and之间的两个语句。指定两个语句之间和不包装它们是语法错误。dowhiledowhile{}

PS更正:do/while我上面关于成为唯一可行变体的说法是不正确的。在@Michael Burr 的回答中,您可以看到另一个合适的变体,该变体将else ((void) 0)技巧用于相同目的。但是,主要原则保持不变。

于 2012-11-26T07:03:26.627 回答
2

这是一个我相信可以安全地做你想做的事的宏:

#define EXIT_CIRCULATION()  \
            if (1) {        \
                /* some statements */   \
                break;                  \
            }                           \
            else                        \
                do {} while (0)

ifhere 与 an 匹配的事实else意味着宏可以安全地在 another 中使用if,并且由于该else子句是无操作do/语句,它提供了与在/while中包装多行宏类似的属性。比如宏需要用分号结束,就好像它是一个普通的语句一样;忘记分号会导致语法错误。它在另一个or子句中表现得很好。dowhileifelse

对你来说最重要的是(我认为),该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
于 2012-11-26T10:51:40.707 回答