do{
//do something
]while(0);
上面是一段使用 do while(0) 的代碼,顯然如上代碼只會執行一次,這樣使用顯然是毫無意義的的(當然莫種情況下還是有意義的,比如在裏面定義局部變量),所以在常規的代碼編寫中,我們並不會使用 do while(0) 這種結構。但是在Linux內核代碼中卻大量使用了do while(0) 這種結構:
那麼,通常在什麼時候使用呢,隨便點擊一個查看(其實其他都是同種類型):
細看,這居然是一個宏,(作爲小白,平時的宏都是一行的),其實像這樣複雜的宏,在內核源碼中非常常用,可以使代碼更加簡潔,也不會像函數那樣降低代碼運行速度。那麼爲什麼要使用 do while(0) 呢,我們使用一下例子分析:
例如我有這樣一個宏:
void fun1(){
printf("fun1\n");
}
void fun2(){
printf("fun2\n");
}
#define ifTrue fun1(); fun2(); //複雜宏
那麼如果我有一下這樣的應用:
#define ifTrue fun1(); fun2();
if(flag)
ifTrue;
預編譯展開宏之後:
#define ifTrue fun1(); fun2();
if(flag)
fun1();
fun2();
那麼就會出現一個問題,無論flag是什麼值 fun2() 都會被執行。程序邏輯就會錯誤。
所以有同學就說了,加個大括號不就行了嗎?就像這樣:
#define ifTrue {fun1(); fun2();} //複雜宏
那麼,程序預編譯展開宏之後將是這樣:
#define ifTrue {fun1(); fun2();}
if(flag)
{fun1(); fun2();};
後面將多出一個分號(單獨的分號代表空語句),對於現在9102的編譯器當然沒問題,但是對於舊編譯器可能就會出現警告甚至是錯誤。怎麼去將宏統一又能消化掉後面的分號呢,do while(0) 結構就很好的解決了上面的所有煩惱,do while() 設計的初心應該是循環控制結構,但是卻被挖掘出另一種用途,這就是程序設計之美!