do..while(0)的用法

do..while(0)的用法

真是的,我用C++还是太少了。这个宏以前明明见过的,但其存在的意义突然就想不起来了。刚才问了下axx大才又知道了一次。赶紧记下来。

这样的宏见过么:

Cpp代码 clip_image001

  1. #define FOO(x) do {\  
  2.     some_code_line_1;\  
  3.     some_code_line_2;\  
  4. } while (0) 
#define FOO(x) do {\
    
    some_code_line_1;\
    
    some_code_line_2;\
    
} while (0)
    


(注意while(0)后面没有分号)

乍一看这个宏不过就是定义了个包含多个语句的local scope,用do..while(0)包围起来简直多此一举。直接这样不就好了么:

Cpp代码 clip_image001

  1. #define FOO(x) {\  
  2.     some_code_line_1;\  
  3.     some_code_line_2;\  
#define FOO(x) {\
    
    some_code_line_1;\
    
    some_code_line_2;\
    
}
    



但问题是这两者不等价……

关键问题是前者定义出来的宏是一个非复合语句,而后者是一个复合语句。C/C++里有些语法结构对复合/非复合语句之间的区别是敏感的,例如说:

Cpp代码 clip_image001

  1. if ( someCond )  
  2.     FOO(x);  
  3. else 
  4.     //... 
if ( someCond )
    
    FOO(x);
    
else
    
    //...
    


要是FOO(x)展开后是一个复合语句,那么FOO(x)后面的分号“;”就会终结整个if语句,导致else子句孤立而出现编译错误。
所以关键是那个while(0)后面不加分号。如果加了分号的话就没意义了。

如果用复合语句版本的宏,就要记得不写那个分号:

Cpp代码 clip_image001

  1. if ( someCond )  
  2.     FOO(x)  
  3. else 
  4.     //... 
if ( someCond )
    
    FOO(x)
    
else
    
    //...
    


但是这样与一般的函数调用风格不统一,所以很多人倾向于使用do..while(0)这个trick来把local scope包起来而不是直接用复合语句({..})。

印象中这类的宏还有一个变种,

Cpp代码 clip_image001

  1. #define FOO(x) switch(0) default: ... 
#define FOO(x) switch(0) default: ...
    


还是怎样的。具体是怎么写的忘记了……以后想起来的话一定得记下来 T T

 

 

do...while(false)的妙用

今天从Java自由人看到一篇Blogdo...while(false)的探讨,刚好解决了一直困扰我的一个小麻烦clip_image001
经常会遇到这样的情况,一大段代码,中间遇到某种情况,比如someObj == null,需要跳出这段代码,但是又不在循环之中,只好处理成这样:

clip_image002clip_image003if(someObj != null)clip_image004{
clip_image005 
//doSomethingclip_image004
clip_image005
  clip_image004
clip_image006clip_image007 
if(someOther fit someCondition)clip_image004{
clip_image005    clip_image004
clip_image008  }

clip_image009}

最后造成一大堆括号,写起来不舒服,可读性也很差。

巧用do...while(false)可以解决这个问题,看下面的代码:

clip_image010function LTrim(s){
clip_image010 
try{
clip_image010   
do{
clip_image010     
if(null==s||s.length<=0)
clip_image010       
break;
clip_image010     
var whitespace=" \t\r\n";
clip_image010     
if(whitespace.indexOf(s.charAt(0))>=0){
clip_image010       
var len=s.length;
clip_image010       
var index;
clip_image010       
for(index=0;index  if(whitespace.indexOf(s.charAt(index))<0)
clip_image010           
break;
clip_image010       
if(index s=s.substring(index);
clip_image010       
else s="";
clip_image010      }
clip_image010    }
while(false);
clip_image010  }
catch(Ab){
clip_image010  s="";
clip_image010  }
clip_image010 
return s;
clip_image010}


这个函数是用来去掉字符串前端的空白。使用do...while(false)的用意就在于在do{}的过程中可以break,使得函数唯一的出口就是最后一行的return
嗯,这是一个不错的方法。以后可以采用,避免过多的嵌套括号。
(
以上部分摘抄Blogdo...while(false)的探讨)

 

你可能感兴趣的:(do..while(0)的用法)