转自http://blog.sina.com.cn/s/blog_628bebe401013tf5.html
一、简单宏定义
二、条件编译
三、复杂宏定义及do{}while(0)的使用
#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)这种无
用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低
#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 { }
现有一个例子: #define PJ_LOG(level,arg) \ dosomething();\ 现在假设有以下应用: if(L==1) PJ_LOG(L,"AAA"); 宏转开为: if(L==1) dosomething(); pj_log_wrapper_1("AAA"); ; if (1 <= pj_log_get_level()) pj_log_wrapper_1("AAA"); ; 假如使用do{}while(0)语句块,进行宏定义: #define PJ_LOG(level,arg)do{ \ dosomething();\ }while(0) 上述应用转开后为: if(L==1) do{ dosomething(); pj_log_wrapper_1("AAA"); }while(0); 这样避免了意外的麻烦。OK现在明白了很多C程序中奇怪的do{}while(0)宏定义了吧 |