真是的,我用C++還是太少了。這個(gè)宏以前明明見(jiàn)過(guò)的,但其存在的意義突然就想不起來(lái)了。剛才問(wèn)了下axx大才又“知道”了一次。趕緊記下來(lái)。 這樣的宏見(jiàn)過(guò)么:
Cpp代碼
#define FOO(x) do {\
some_code_line_1;\
some_code_line_2;\
} while (0)
(注意while(0)后面沒(méi)有分號(hào)) 乍一看這個(gè)宏不過(guò)就是定義了個(gè)包含多個(gè)語(yǔ)句的local scope,用do..while(0)包圍起來(lái)簡(jiǎn)直多此一舉。直接這樣不就好了么:
#define FOO(x) {\
}
但問(wèn)題是這兩者不等價(jià)…… 關(guān)鍵問(wèn)題是前者定義出來(lái)的宏是一個(gè)非復(fù)合語(yǔ)句,而后者是一個(gè)復(fù)合語(yǔ)句。C/C++里有些語(yǔ)法結(jié)構(gòu)對(duì)復(fù)合/非復(fù)合語(yǔ)句之間的區(qū)別是敏感的,例如說(shuō):
if ( someCond )
FOO(x);
else
//...
要是FOO(x)展開(kāi)后是一個(gè)復(fù)合語(yǔ)句,那么FOO(x)后面的分號(hào)“;”就會(huì)終結(jié)整個(gè)if語(yǔ)句,導(dǎo)致else子句孤立而出現(xiàn)編譯錯(cuò)誤。 所以關(guān)鍵是那個(gè)while(0)后面不加分號(hào)。如果加了分號(hào)的話(huà)就沒(méi)意義了。 如果用復(fù)合語(yǔ)句版本的宏,就要記得不寫(xiě)那個(gè)分號(hào):
FOO(x)
但是這樣與一般的函數(shù)調(diào)用風(fēng)格不統(tǒng)一,所以很多人傾向于使用do..while(0)這個(gè)trick來(lái)把local scope包起來(lái)而不是直接用復(fù)合語(yǔ)句({..})。 印象中這類(lèi)的宏還有一個(gè)變種,
#define FOO(x) switch(0) default: ...
還是怎樣的。具體是怎么寫(xiě)的忘記了……以后想起來(lái)的話(huà)一定得記下來(lái) T T
do...while(false)的妙用
今天從Java自由人看到一篇Blog:do...while(false)的探討,剛好解決了一直困擾我的一個(gè)小麻煩經(jīng)常會(huì)遇到這樣的情況,一大段代碼,中間遇到某種情況,比如someObj == null,需要跳出這段代碼,但是又不在循環(huán)之中,只好處理成這樣:
if(someObj != null){ //doSomething if(someOther fit someCondition){ }}
最后造成一大堆括號(hào),寫(xiě)起來(lái)不舒服,可讀性也很差。巧用do...while(false)可以解決這個(gè)問(wèn)題,看下面的代碼:
function LTrim(s){ try{ do{ if(null==s||s.length<=0) break; var whitespace=" \t\r\n"; if(whitespace.indexOf(s.charAt(0))>=0){ var len=s.length; var index; for(index=0;index if(whitespace.indexOf(s.charAt(index))<0) break; if(index s=s.substring(index); else s=""; } }while(false); }catch(Ab){ s=""; } return s;}
這個(gè)函數(shù)是用來(lái)去掉字符串前端的空白。使用do...while(false)的用意就在于在do{}的過(guò)程中可以break,使得函數(shù)唯一的出口就是最后一行的return。嗯,這是一個(gè)不錯(cuò)的方法。以后可以采用,避免過(guò)多的嵌套括號(hào)。(以上部分摘抄Blog:do...while(false)的探討)
posted on 2009-03-11 13:09 肥仔 閱讀(4065) 評(píng)論(0) 編輯 收藏 引用 所屬分類(lèi): C++ 基礎(chǔ)
Powered by: C++博客 Copyright © 肥仔