[英]C multi-line macro issue: why not use if(1){…} instead of do{…}while(0) in multi-line macro definition
我想調用循環中的多行宏來打破/繼續它。
如果我在多行宏定義中使用“do {...} while(0)”,則break / continue僅對“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 ++語法中沒有其他語句可以滿足此要求。 (這是一個不准確的聲明,請參閱下面的“PS”)
在所有其他情況下(包括你的if (1) {...}
) ;
宏調用之后將被視為另一個獨立的獨立空語句。 這樣就不可能寫出一個;
在宏調用之后,當它在需要完全一個語句的上下文中使用時(如if-else
真分支或do/while
循環的主體)。
例如,如果您定義
#define A() if (1) {}
那么這段代碼將無法編譯
do
A();
while (1);
因為它將被取代
do
if (1) {}; /* <- two statements, not one */
while (1);
這實際上是do
和while
之間的兩個陳述。 在do
和while
之間指定兩個語句而不將它們包裝到{}
是語法錯誤。
PS更正:我上面提到的關於do/while
唯一可行的變體的說法是不正確的。 在@Michael Burr的回答中,你可以看到另一個合適的變體,它使用else ((void) 0)
技巧用於相同的目的。 但是,主要原則仍然是相同的。
這是一個我認為可以安全地做你想要的宏:
#define EXIT_CIRCULATION() \
if (1) { \
/* some statements */ \
break; \
} \
else \
do {} while (0)
if
這里與else
匹配的事實意味着宏可以安全地在另一個內部使用if
,並且因為else
子句是do-nothing 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.