C語言中do{...}while(0)的秒用
今天看了些有關do{...}while(0)秒用的文章,覺得寫的很好,這裡總結下分享給大家。
這裡分享的有3個用法,分别是:
1.避免空的宏定義在編譯時出現warning。
2.多個語句一起,定義成一個宏時,增加代碼适應(特别是條件語句調用這類宏要注意)
3.避免部分goto語句的使用
1.避免空的宏定義在編譯時出現warning
//例如:
#define foo() do{}while(0)
2.多個語句一起,定義成一個宏時,增加代碼适應(特别是條件語句調用這類宏要注意),以下if(0)和if(1)在實際應用時是if(表達式),表示表達式假和真。
//例如:一個宏包含以下兩個語句,
#define foo()
fun1();
fun2;
編譯器預處理的時候
if(1)foo();
//此時就相當于下面的語句,
if(0)fun1();
fun2();//邏輯上多執行的代碼,會導緻系統BUG
;//邏輯上多執行的代碼
如果使用do{...}while(0)就可以解決上面的問題
#define foo()
do{
fun1();
fun2();
}while(0)
//對于下面的語句
if(0) foo();
//編譯後的執行如下:
if(0) do{
fun1();
fun2();
}while(0);
這樣就不會出現上面那種有邏輯上不該執行的代碼被執行的問題。當然這裡也可以用其他方法避免這個問題,比如加大括号{}
#define foo() {fun1();fun2;}
編譯器會預處理下面語句
if(0) foo();
//編譯後的執行如下:
if(0) {
fun1();
fun2();
}
;//會多個;号,但是也沒有邏輯上的問題
語句塊宏定義時注意的就是這些,另外在寫if語句時,盡量後面要加大括号,避免出錯,例如上面的if(0){foo();},加上大括号{}也不會有問題。
3.避免部分goto語句的使用
//例如:如果一個函數要分配一些資源,然後中途遇到錯誤,要退出函數,退出前要釋放資源,代碼結構可能如下:
bool foo(){
int *p = (int*)malloc(5*sizeof(int));
bool bOk = true;
//執行并處理錯誤
bOk = fun1();
if(!bOk){
free(p);
p=NULL;
return false;
}
bOk = fun2();
if(!bOk){
free(p);
p=NULL;
return false;
}
bOk = fun3();
if(!bOk){
free(p);
p=NULL;
return false;
}
//......
//執行成功,釋放資源并返回ture
free(p);
p = NULL;
return true;
}
這裡就覺得很多代碼冗餘,然而使用溝通可以很好的解決冗餘的部分,代碼如下:
bool foo(){
int *p = (int*)malloc(5*sizeof(int));
bool bOk = true;
//執行并處理錯誤
if(!fun1()) goto errorlable;
if(!fun2()) goto errorlable;
if(!fun3()) goto errorlable;
//......
//執行成功,釋放資源并返回ture
free(p);
p = NULL;
return true;
//冗餘部分的,錯誤返回代碼
errorlable:
free(p);
p = NULL;
return false;
}
然後C語言中過多的使用goto語句會提高程序的靈活性,繁雜點的程序會讓程序員捉摸不定,程序跳來跳出,難以捉摸,容易邏輯上産生混淆從而出現BUG。對于上面的這種情況使用do{...}while(0)就可以很好的解決這些跳來跳出的問題,代碼結構如下:
bool foo(){
//分配資源
int *p = (int*)malloc(5*sizeof(int));
bool bOk = true;
//執行并處理錯誤
do{
bOk = fun1();
if(!bOk)break;
bOk = fun2();
if(!bOk)break;
bOk = fun3();
if(!bOk)break;
//......
}while(0);
//釋放資源并返回bOk
free(p);
p = NULL;
return bOk;
}
,