最近在新公司的代碼中發現到處用到do{...}while(0),google了一下,發現Stack Overflow上早有很多討論,總結了一下討論,加上自己的理解,do{...}while(0)的價值主要體現在:
1. 增加代碼的適應性
下面的宏定義沒有使用do{...}while(0)
#define FOO(x) foo(x); bar(x);
這樣宏定義,單獨調用不會出現問題,例如:
FOO(100)
宏擴展後變成:
foo(x);bar(x);
這樣調用FOO沒有任何問題,但是FOO(x)不能放入控制語句中,例如
if (condition) FOO(x); else ...;
經過宏擴展後,變成了
if (condition) foo(x);bar(x); else ...;
這樣就導致了語法錯誤,語法錯誤並不可怕,在編譯階段就能發現,更致命的是他有可能導致邏輯錯誤,這種錯誤編譯器發現不了,一出這種問題,程序員就抓狂吧。例如:
if (condition) FOO(x);
這段代碼經過擴展後變成:
if (condition) foo(x); bar(x);
這樣一來,無論condition是true還是false,bar(x)都會被調用。有沒有被這煎熬過的兄弟啊?
這時候do{...}while(0)的價值就體現出來了,修改一下FOO的定義
#define FOO(x) do { foo(x); bar(x); } while (0)
這樣FOO,放入控制語句中就沒有問題了。
也許有人說:把foo(x);bar(x)用大括號括起來不就行了嗎?比如這樣定義:
#define FOO(x) { foo(x); bar(x); }
再看下面代碼:
if (condition) FOO(x); else ...;
擴展後:
if (condition) {foo(x);bar(x);} ; //注意最後這個分號,語法錯誤 else ...;
照樣語法錯誤;
2.增加代碼的擴展性
我理解的擴展性,主要是宏定義中還可以引用其他宏,比如:
#define FOO(x) do{OTHER_FOO(x)} while(0)
這樣我們不用管OTHER_FOO是但語句還是符合語句,都不會出現問題
3.增加代碼的靈活性
靈活性主要體現在,我們可以從宏中break出來,例如下面的定義:
#define FOO(x) do{ \ foo(x); \ if(condition(x)) \ break; \ bar(x) \ ..... \
} while(0)