do{}while(0)大致有两种基本用法:
1. 宏定义
当宏定义中有多个语句时,采用do{}while(0)可以避免不必要的错误。
我们从一般的宏定义引出使用do{}while(0)的好处
1.1 原始定义
#define return_if_failed(p) if (p) { /
printf(#p“ failed!/n”); /
return; /
}
该宏在使用if else语句时出现问题
例如:1> if (str)
2> return_if_failed(p);
3> else
4> ...
分析:首先会出现编译错误,因为第2>行后的";"实际上是代表空语句,也间接表明了if语句的结束,所以后面的else会出现编译错误。
去掉该";"后,就不会有编译错误,但是出现语义错误。第3>行的else本来和第1>的if搭配,但是宏替换后和宏中的if搭配了。
1.2 改进定义一——加入{}
#define return_if_failed(p) { /
if (p) { /
printf(#p“ failed!/n”); /
return; /
} /
}
这样定义可以消除语义错误,但是还是无法消除语法错误,除非按照下面的写法:
例如:1> if (str)
2> return_if_failed(p) // 即去掉最后的";"
3> else
4> ...
分析:这显然不符合编程习惯
1.3 改进定义一——通用宏定义,使用do{}while(0)
#define return_if_failed(p) do{ if (p) { printf(#p“ failed!/n”); return;}}while(0)
// 注意whlie(0)后没有";"
分析:这样既没有语法错误,也不会产生语义错误。
当然如果按照下面方法使用宏,则1.1 1.2 1.3都不会产生错误(语法,语义)
例如:1> if (str) {
2> return_if_failed(p);
3>} else {
4> ...
5>}
诚然,这是一个好的,应该提倡的编程习惯,但一般这样的宏都是作为library的一部分出现的,而对于一个library的作者,他所要做的就是让其库具有通用性,强壮性,因此他不能有任何对库的使用者的假设,如其编码规范,技术水平等。(该句为一位网上老兄的话,很有道理)
2. 消除代码冗余
经常会遇到这样的程序:
if (a) {
...
return false;
} else if (b) {
...
return false;
} else if (c) {
...
return false;
} else if (d) {
...
return false;
} else if (d) {
...
return false;
}
很多的return false;
使用do{}while(0)就变的很简单了
do {
if (a) {
...
break;
} else if (b) {
...
break;
} else if (c) {
...
break;
} else if (d) {
...
break;
} else if (e) {
...
break;
}
} while (0);
free(p);
p = NULL;
return false;
当然也可以用goto语句来实现
free(p);
p = NULL;
free(p);
p = NULL;
free(p);
p = NULL;
free(p);
p = NULL;
free(p);
p = NULL;