玩linux多多少少會看到一個用法 do xxx while(0)。從邏輯上來看,似乎沒什麼特別的,甚至會懷疑是否多此一舉 (while 0不就是直接跳出嗎?)。事實上,這是有一定用途的,主要是避免文法錯誤。在define macro時,只有一個語句,如#define foo(x) bar(x); 這樣多半不會有問題。但較複雜的macro搭配if else等flow control時,就會產生文法上的問題,看下例:
#define foo(x) bar(x); qoo(x);
int main(int argc, char* argv[])
{
if(1)
foo(1);
else
printf("in else\n");
}
latrell:~/temp/ctest$ gcc dowhile.c
dowhile.c: In function ‘main’:
dowhile.c:11: error: ‘else’ without a previous ‘if’
使用-E看preprocess的結果如下,多了一個分號,文法錯誤。
int main(int argc, char* argv[])
{
if(1)
bar(1); qoo(1);;
else
printf("in else\n");
}
用大括弧呢?#define {foo(x) bar(x); qoo(x);}
顯示一樣的compiler error,因為還是多了一個分號。
int main(int argc, char* argv[])
{
if(1)
{bar(1); qoo(1);};
else
printf("in else\n");
}
當然可以寫成
int main(int argc, char* argv[])
{
if(1)
foo(1) //不加結束的分號
else
printf("in else\n");
}
這樣的確可以避開compile error,不過這樣不符合一般寫法,也很不易讀。
正解為do while 0,如下:
#define foo(x) do {bar(x); qoo(x);} while (0)
展開如下:
int main(int argc, char* argv[])
{
if(1)
do {bar(1); qoo(1);} while (0);
else
printf("in else\n");
}
do while 0具有封閉的功能,使用macro可多加利用,避免一些莫名其妙的bug。
Note: 通常macro後是不加分號的,所以不會寫成#define foo(x) do {bar(x); qoo(x);} while (0);
留言列表