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