其實關注do{}while(0)的用法還是一次偶然的機會
當時還在實習,連個工作都找不到,面試的時候有個面試題。
請問do{}while(0)這樣寫有什么作用?
我當時想這有什么作用,就是里面的代碼塊執行一遍就是了唄,費勁,胡亂答了幾句在上面。
雖然那公司把我錄了,但是真的還是很坑的一家公司,呆了兩個月自己閃人了。
后面覺得這問題奇怪,就在網上搜了很多關于do{}while(0)用法的文章來看。
總體的作用就是一下幾個方面:
1.?輔助定義復雜的宏,避免引用的時候出錯
下面是Cocos2dx的一個宏定義:
~~~
#define CC_SAFE_DELETE(p) ? ? ? ? ? ?do { if(p) { delete (p); (p) = 0; } } while(0)
~~~
不得不說Cocos2dx的源碼寫得還是很嚴謹的
但是假設這里去掉do{}while(0)和里面的if(p)然后變成下面的這個樣子:
~~~
#define CC_SAFE_DELETE(p) ? ? ? ? ? ?delete (p); (p) = 0;
~~~
如果用這個宏定義在代碼中使用,像以下代碼
~~~
if(NULL != p)
CC_SAFE_DELETE(p)
else
wordOff();
~~~
這段代碼就有問題了:
a. 因為if分支后面有兩條語句了,所以編譯就會出問題。這里如果養成好習慣別裝大神,加上一對{}這個問題也可以解決。
b. 還有個問題就是如果沒有else分支里面的(p)=0會永遠執行。因為if后面沒括號只執行緊鄰的一句代碼。
我們在寫代碼的時候可以讓代碼嚴謹細致一點,加一點括號多兩行,但是你以后修改Bug不會那么痛苦。
2. 跳出代碼塊,不執行后面的語句
其實這個功能比較實用一些
很多的條件判斷可以用到do{}while(0)的寫法
這個用法其實也很簡單,精髓就在于用break或者continue來控制流程,跳出代碼塊。
就像下面的一串代碼,看看就能明白了:
~~~
bool bFlag = false;
do {
if (!bFlag) {
print("The flag is FALSE");
break;// 用break(continue)跳出了之后就不用執行下面的語句了
//continue;
}
print("Work off.\n");
} while (0);
~~~
這里的break跳出循環就有點類似于goto語句了,不過goto太粗糙。
可以自己寫個do{}while(0)的代碼語句來調試調試,自然而然就領悟了。
還是鄧大爺那句話啊,實踐是檢驗真理的唯一標準。
下面是我的項目中通信塊用到的do{}while(0)的示例,可以看看加深印象。
~~~
do
{
BYTE byProtocol = *(LPBYTE)pMsg;
if (byProtocol <= S2C_BEGIN || byProtocol >= S2C_END){
printf("Invalid Protocol %d\n", (INT)byProtocol);
assert(false);
continue;
}
INT nProSize = GetProtocolSize(byProtocol);
if (nProSize == -1){
nProSize = PROTOCOL_MSG_SIZE + (*(USHORT*) (((CHAR*)pMsg) + PROTOCOL_MSG_SIZE));
}
printf(">>>>ProtocolType %d, Size:%d != ProSize:%d\n", (INT)byProtocol, nSize, nProSize);
//協議出錯跳出
if (nProSize != nSize){
printf("Invalid ProtocolType %d, Size:%d != ProSize:%d\n", (INT)byProtocol, nSize, nProSize);
assert(false);
continue;
}
//網絡斷開
if (!ProcessFunc[byProtocol]){
assert(false);
continue;
}
if(GHLandProtocol::m_pGameSence!=NULL){
(this->*ProcessFunc[byProtocol])(pMsg, nSize);
}
} while(FALSE);
~~~
好了,關于do{}while(0)我也就只學習到這里。
- 前言
- C++讀取配置文件
- 結構體內存對齊后所占內存空間大小的計算
- do{}while(0)的妙用
- Cocos2dx實現翻牌效果(CCScaleTo與CCOrbitCamera兩種方式)
- C++的error LNK2019: 無法解析的外部符號編譯錯誤
- Java使用JNI調用C++的完整流程
- strupr與strlwr函數的實現
- strcat函數實現
- Windows上VS使用pthread重溫經典多線程賣票(pthreads-w32-2-8-0-release.exe)(windows上使用pthread.h)
- pthread的pthread_join()函數理解實驗
- 順序存儲結構和鏈式存儲結構的選擇
- C語言冒泡排序
- VS看反匯編、寄存器、內存、堆棧調用來學習程序設計
- 快速排序
- C++的構造函數初始化列表
- fatal error C1083: 無法打開包括文件: “SDKDDKVer.h”: No such file or directory
- C++實現簡單的String類