do … while(0) 的妙用 gaunthan Posted on Feb 12 2017 ? C Language ? ## 用于宏函数 ### 强制添加分号 当do ... while(0)用于宏函数的时候,调用该宏函数便和普通的函数一样,需要添加分号: ```cpp #define MYFREE(p) \ do \ { \ if(NULL != p) \ free(p) \ p = NULL; \ }while(0) ``` ### 避免if else匹配问题 ```cpp #define PRINT_STRING(isDoc) \ if(isDoc) \ printDoc() void MyPrint(void) { . . . if(doc exists) PRINT_STRING(doc); else ERROR("No such doc.") } ``` 像上面这样的代码,宏的展开会使得if else匹配出现问题。而使用do ... while(0)却不会引起类似的问题: ``` #define PRINT_STRING(isDoc) \ do { \ if(isDoc) \ printDoc(); \ }while(0) ``` ## 消除代码冗余 ### 清除goto语句 通常,如果在一个函数中开始要分配一些资源,然后在中途执行过程中如果遇到错误则退出函数,当然,退出前先释放资源,我们的代码可能是这样: ```cpp bool Execute() { // 分配资源 int *p = new int; bool bOk(true); // 执行并进行错误处理 bOk = func1(); if(!bOk) { delete p; return false; } bOk = func2(); if(!bOk) { delete p; return false; } // .......... // 执行成功,释放资源并返回 delete p; return true; } ``` 这里一个最大的问题就是代码的冗余——每增加一个操作,就需要做相应的错误处理,非常不灵活。于是想到了goto: ```c bool Execute() { // 分配资源 int *p = new int; bool bOk(true); // 执行并进行错误处理 bOk = func1(); if(!bOk) goto errorhandle; bOk = func2(); if(!bOk) goto errorhandle; // .......... // 执行成功,释放资源并返回 delete p; return true; errorhandle: delete p; return false; } ``` 代码冗余是消除了,但由于goto不符合软件工程的结构化原则,而且有可能使得代码阅读性降低,这个时候可以用`do...while(0)`进行统一的管理: ```cpp bool Execute() { // 分配资源 int *p = new int; bool bOk(true); do { // 执行并进行错误处理 bOk = func1(); if(!bOk) break; bOk = func2(); if(!bOk) break; // .......... }while(0); // 释放资源 delete p; return bOk; } ``` ## References - [ do...while(0) 在宏定义中的巧妙用法](http://blog.csdn.net/luoweifu/article/details/38563161) - [do...while(0) 的妙用](http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html) 赏 Wechat Pay Alipay C语言 获取随机数 设计模式指南