本文轉(zhuǎn)自徐飛翔的“do{}while(false)結(jié)構(gòu)的妙用”
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
看源碼的時(shí)候,發(fā)現(xiàn)某個框架的源碼里面經(jīng)常出現(xiàn)如下片段:
do{
if (ASSERT(some_input_1) && ASSERT(some_input_2)) {
...
}
} while(false)
我對于do{} while(false)
結(jié)構(gòu)的使用,在此之前無非兩種,第一種是基本用法,也就是把它當(dāng)成循環(huán)結(jié)構(gòu)使用,和for(;;)
,while(){}
沒太大區(qū)別;還有一種用法是用在宏定義中,如下所示:
#define LARGER(x,y) x > y? x:y
int a = 2 * LARGER(10,30);
此時(shí)我們本來期望a = 60,其實(shí)因?yàn)樽址娲脑?,?shí)際上是int a = 2 * x > y?x:y =30。這就是bug的源頭之一。通過do{macro_code} while(false)結(jié)構(gòu),能對macro_code進(jìn)行很好的分割。
然而,這個結(jié)構(gòu)還有一個好處,其本質(zhì)是一個循環(huán)結(jié)構(gòu),意味著它可以提前break,在多條件判斷的環(huán)境下是一個作為對goto
的很好的取代。如:
do {
if (ASSERT(some_input_1) && ASSERT(some_input_2)) {
ERR_LOG('log_info', pFile);
break;
}
if (IS_EXIST(path)) {
ERR_LOG('log_info', pFile);
break;
}
// the residual code you need , the main stream
} while(false)
通過這種手段,基于作為入口條件判斷,如果一旦不符合條件,可以直接break,跳到循環(huán)之外,這相當(dāng)于很好地應(yīng)用了goto的功能,而沒有引入goto的負(fù)作用(全局跳轉(zhuǎn),難以維護(hù))。
Reference
[1]. https://stackoverflow.com/questions/2314066/do-whilefalse