from: http://blog.csdn.net/chenhu_doc/article/details/856468
构建复用库的时候,发现许多宏定义都使用了do...while(0),比如说:
为什么要用do{} while(0)呢?Internet 一下,原因如下:
那么以下代码:
展开就是:
这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。所以必须要保证宏定义整体被当成一个模块插入。如果直接用{}括起来,会怎么样呢?
换成do{} while(0)呢?
展开:
为了消除冗余,我们可以用goto语句来集中处理:
但是如果不喜欢用goto语句怎么办?那么就用do{}while(0)吧!
from: http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html
一、存在的意义
宏定义中的do...while(0)构建复用库的时候,发现许多宏定义都使用了do...while(0),比如说:
#define str_safe_cpy(dest, src, size) \
do { \
strncpy((dest), (src), (size)); \
dest[size] = 0; \
} while (0)
为什么要用do{} while(0)呢?Internet 一下,原因如下:
#define macro(condition) if(condition) dosomething();
那么以下代码:
if(temp)
macro(i);
else
doanotherthing();
展开就是:
if(temp)
if(condition) dosomething(); ;
else
doanotherthing();
这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。所以必须要保证宏定义整体被当成一个模块插入。如果直接用{}括起来,会怎么样呢?
#define macro(condition) { if(condition) dosomething(); }
展开:
if(temp)
{if(condition) dosomething(); }
; //会多出一个分号
else
doanotherthing();
gcc编译时报错:error: expected expression before ‘else’,但是如果只是单纯滴调用macro(i);也是可以的,即调用时不影响代码逻辑结构的,如:
int i = 2;
if (i > 1)
macro(i);
printf ("%d\n", i);
换成do{} while(0)呢?
#define macro(condition) \
do { \
if(condition) \
dosomething(); \
} while(0)
展开:
if(temp)
do {
if(condition)
dosomething();
} while(0); //刚好
else
doanotherthing();
二、其他使用方法
除了像第一点用于宏之中,还可以用于替代goto语句,美化代码。
程序需要处理多种情况,会导致代码冗余,如下:
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;
}
为了消除冗余,我们可以用goto语句来集中处理:
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;
}
但是如果不喜欢用goto语句怎么办?那么就用do{}while(0)吧!
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;
}