宏定义中使用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入输出函数,參数都是可变的.在调试程序时.我们可能希望定义一个參数可变的输出函数来记录日志,那么用可变參数的宏是一 ...
随机推荐
-
spi controller
http://blog.csdn.net/droidphone/article/details/24353293 http://www.china-cpu.com/supports/article/0 ...
-
SQLite使用方法 SQLiteOpenHelper操作(转)
SQLiteOpenHelper主要用于 创建数据库 SQLiteDatabase 主要用于 执行sql语句 程序内使用SQLite数据库是通过SQLiteOpenHelper进行操作 1. ...
-
Base
base 关键字用于从派生类中访问基类的成员: 调用基类上已被其他方法重写的方法. 指定创建派生类实例时应调用的基类构造函数. 基类访问只能在构造函数.实例方法或实例属性访问器中进行. 从静态方法中使 ...
-
Retrofit分析-漂亮的解耦套路
没耐心自己分析源码的同学,还可以参考Stay录制的视频版 Retrofit分析-漂亮的解耦套路(视频版) 万万没想到Retrofit会这么火,在没看源码之前,我简单的认为是因为它跟OkHttp同出一源 ...
-
mysql 查询大量数据内存溢出
使用非buffer 的sql 查询 比如pymysql 的 pymysql.cursor.SSCursion
-
js 多媒体audio video
本文主要简单的介绍一下audio 和 video两个标签的用法 <audio src="music.mp3"></audio> <video src= ...
-
Android从无知到有知——NO.4
因为我们做的是手机安全卫士,因此,我们需要一个地图定位功能,些相关的项目,也有一些教程.到百度官方下载了相关的jar包和API,但自己建项目的时候却不是那么顺利,bug不断,弄得心烦意乱,最后最终臣服 ...
-
微信js的引用
public function seach_accurate(){ import ( 'Class.Wechat', APP_PATH ); $weObj = new WeChat (array()) ...
-
PDF文件优缺点
PDF的优点: 一般公司的公文档都是用PDF格式传递给员工,因为PDF可防止他人无意中触到键盘修改文件内容. 再有就是,当我们将毕业设计报告用word编辑后,发送给导师查看时,也建议采用PDF格式.因 ...
-
java RE Validation常用
import java.util.regex.Matcher; import java.ulil.regex.Pattern; public class RegExpUtil { public sta ...