do{}while(0)的妙用

最后更新于:2022-04-01 20:13:20

其实关注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)我也就只学习到这里。
';