宏定义中使用do{}while(0)的好处 (转载)
宏定义中使用do{}while(0)的好处
#define MACRO_NAME(para) do{macro content}while(0)
#define foo(x) /
action1(); /
action2();
if(NULL == pPointer)
foo();
#define switch(x,y) {int tmp; tmp="x";x=y;y=tmp;}
if(x>y)
switch(x,y);
else //error, parse error before else
otheraction();
从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无
用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低
但是,最近在读我们项目的代码时,却发现了do...while的一些十分聪明的用法,不是用来做循环,而是用作其他来提高代码的健壮性。
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true); // 执行并进行错误处理
bOk = func1();
if(!bOk)
{
delete p;
p = NULL;
return false;
} bOk = func2();
if(!bOk)
{
delete p;
p = NULL;
return false;
} bOk = func3();
if(!bOk)
{
delete p;
p = NULL;
return false;
} // .......... // 执行成功,释放资源并返回
delete p;
p = NULL;
return true; }
version 2
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true); // 执行并进行错误处理
bOk = func1();
if(!bOk) goto errorhandle; bOk = func2();
if(!bOk) goto errorhandle; bOk = func3();
if(!bOk) goto errorhandle; // .......... // 执行成功,释放资源并返回
delete p;
p = NULL;
return true; errorhandle:
delete p;
p = NULL;
return false; }
version3
bool Execute()
{
// 分配资源
int *p = new int; bool bOk(true);
do
{
// 执行并进行错误处理
bOk = func1();
if(!bOk) break; bOk = func2();
if(!bOk) break; bOk = func3();
if(!bOk) break; // .......... }while(0); // 释放资源
delete p;
p = NULL;
return bOk; }
如果你是C++程序员,我有理由相信你用过,或者接触过,至少听说过MFC, 在MFC的afx.h文件里面,
#define AFXASSUME(cond) do { bool __afx_condVal=!!(cond); ASSERT(__afx_condVal);
__analysis_assume(__afx_condVal); } while(0)
#define SAFE_DELETE(p) do{ delete p; p = NULL} while(0)
#define SAFE_DELETE(p) delete p; p = NULL;
if(NULL != p) SAFE_DELETE(p)
else ...do sth...
就有两个问题,
1) 因为if分支后有两个语句,else分支没有对应的if,编译失败
2) 假设没有else, SAFE_DELETE中的第二个语句无论if测试是否通过,会永远执行。
你可能发现,为了避免这两个问题,我不一定要用这个令人费解的do...while, 我直接用{}括起来就可以了
#define SAFE_DELETE(p) { delete p; p = NULL;}
的确,这样的话上面的问题是不存在了,但是我想对于C++程序员来讲,
在每个语句后面加分号是一种约定俗成的习惯,这样的话,以下代码:
if(NULL != p) SAFE_DELETE(p);
else ...do sth...
其else分支就无法通过编译了(原因同上),所以采用do...while(0)是做好的选择了。
也许你会说,我们代码的习惯是在每个判断后面加上{}, 就不会有这种问题了,也就不需要do...while了,如:
if(...)
{
}
else
{
}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一部分出现的,
而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,
因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等
宏定义中使用do{}while(0)的好处 (转载)的更多相关文章
- define宏定义中的#,##,@#及\符号
define宏定义中的#,##,@#及\符号 在#define中,标准只定义了#和##两种操作.#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串. 1.# (string ...
- 宏定义中的##操作符和... and _ _VA_ARGS_ _
1.Preprocessor Glue: The ## Operator 预处理连接符:##操作符 Like the # operator, the ## operator can be used i ...
- C语言在宏定义中使用语句表达式和预处理器运算符
语句表达式的亮点在于定义复杂功能的宏.使用语句表达式来定义宏,不仅可以实现复杂的功能,而且还能避免宏定义带来的歧义和漏洞.下面以一个简单的最小值的宏为例子一步步说明. 1.灰常简单的么,使用条件运算符 ...
- C语言宏定义中的#和##的作用【转】
本文转载自:http://my.oschina.net/shelllife/blog/123202 在宏定义中#和##的作用是:前者将宏定义的变量转化为字符串:后者将其前后的两个宏定义中的两个变量无缝 ...
- #define宏定义中## #@ # \ 符号使用
C/C++ 宏命令的神奇用法. 先看下面三条语句: #define Conn(x,y) x##y#define ToChar(x) #@x#define ToString(x) ...
- do {...} while (0) 在宏定义中的作用
如果你是一名C程序员,你肯定很熟悉宏,它们非常强大,如果正确使用可以让你的工作事半功倍.然而,如果你在定义宏时很随意没有认真检查,那么它们可能使你发狂,浪费N多时间.在很多的C程序中,你可能会看到许多 ...
- C do {...} while (0) 在宏定义中的作用
如果你是一名C程序员,你肯定很熟悉宏,它们非常强大,如果正确使用可以让你的工作事半功倍.然而,如果你在定义宏时很随意没有认真检查,那么它们可能使你发狂,浪费N多时间.在很多的C程序中,你可能会看到许多 ...
- C语言可变参数在宏定义中的应用
在C语言的标准库中,printf.scanf.sscanf.sprintf.sscanf这些标准库的输入输出函数,参数都是可变的.在调试程序时,我们可能希望定义一个参数可变的输出函数来记录日志,那么用 ...
- C在宏定义中使用的语言可变参数
于C标准库的语言,printf.scanf.sscanf.sprintf.sscanf入输出函数,參数都是可变的.在调试程序时.我们可能希望定义一个參数可变的输出函数来记录日志,那么用可变參数的宏是一 ...
随机推荐
- mysql数据库在Navicat Premium连接的时候出现1862错误
navicat连接打开时报1862的错误, 很就没有连接mysql看看了,今天连接的时候发现本机的mysql链接不上了,在cmd中执行动作的时候也会叫你去set password,做设置密码的动作时会 ...
- dedecms _ 当前位置问题的代码
{dede:field name='position' runphp='yes'} $tc=" > "; $tf=split($tc,@me); $tn=count($tf) ...
- nsfocus-笔试题
1.描述sendmail原理及通讯机制 sendmail程序接受到待发邮件后,通过关键字@判断邮件的格式是否符合要求,匹配成功后提取邮件后缀域名信息并查询DNS数据库相关MX(邮件专用)记录,若有匹配 ...
- 关于css中overflow的一些理解
在做移动端开发的时候,遇到过这么个问题:要把图片进行放大,但有时候图片比较长,一个手机的版面看不了,于是需要用到overflow的属性,刚开始用了overflow-y:scroll, 于是问题来了,如 ...
- Zookeeper,也要接触起来啦
分布式的东东,就是部署也方便,但管理,想法,大集群应用是要点...! 参考如下URL简单实现 ,以后应用时多留意. http://blog.csdn.net/shirdrn/article/detai ...
- IntelliJ IDEA: maven & jetty 开发 java web
之前使用eclipse + maven + jetty开发java web应用,本着no zuo no gain的想法, 折腾了一下Intellj idea下开发环境的搭建,顺带学习了maven re ...
- url中的jsessionid解释
(1) 这是一个保险措施 因为Session默认是需要Cookie支持的 但有些客户浏览器是关闭Cookie的 这个时候就需要在URL中指定服务器上的session标识,也就是5F4771183629 ...
- Xmind 快捷键
Xmind 快捷键 快捷键(Windows) 快捷键(Mac) 描述 Ctrl+N Command+N 建立新工作簿 Ctrl+O Command+O 开启工作簿 Ctrl+S Command+S 储 ...
- Ext.window的close的问题
以前每次都是用的hide,关闭后隐藏窗体,下一次点击再打开,这种方法在我的随笔里面有,可是现在遇到一个问题,我的窗体里面有个formpanel,formpanel每一项都有一个默认值,意思就是修改的时 ...
- 基本NT式驱动代码结构
#include <ntddk.h> void DriverUnload(IN PDRIVER_OBJECT DriverObject);NTSTATUS MyCreateClose(IN ...