C语言宏定义中出现的do...while(0)

在很多c/c++的头文件中,可能会在宏定义里面看到do...while(0)来包含一段代码。

这段循环本质上会确定执行一次,作用有点类似一组花括号包含的代码段。

但他有个这样做的隐藏好处:

主要用来解决宏定义使用时可能的问题

先看一段代码

#define __test0() f1(); f2();
#define __test1() {f1(); f2();}
#define __test2() do {f1(); f2();} while(0)

int main() {
    if (condition)
        __test();
    else
        printf("error");
}

这段代码中,首先是定义一簇__test()函数,用来一次性调用f1()和f2()(这里代表的是一个宏定义执行了多行代码的情况)。

__test0()可能是最常见的情况,但考虑到如果if没有跟花括号这就属于两条语句,所以引申出__test1()。但如果if语句同时也跟了else语句,__test1()就也会引发语法错误(当然,这里如果没有以分号结束不会有错,但可能不太符合日常编码习惯)。但是使用__test2()时,一方面会比较符合我们日常的编码习惯,如果不以分号结束此处会报错,另一方面__test2()的调用同时适用与if语句是否后跟花括号的两种情况。

// 调用__test1()经过预处理后的代码
int main() {
	if (1 > 0) 
		{f1(); f2();};
	else
		printf("false");

	return 0;
}

// 调用__test2()经过预处理后的代码
int main() {
	if (1 > 0) 
		do {f1(); f2();} while(0);
	else
		printf("false");

	return 0;
}

读者可以分别把三个宏定义带入到if成立时候的调用处,看看程序的执行情况。

这里是专门设计的一种特殊情况:if语句成立时,代码体没有花括号,并且后有else语句。正常情况下,如果程序使用规范一点写法if和else都使用花括号包含起来代码体,其实这里三种宏定义效果是一样的。

这里主要是讨论的宏定义中采用do...while(0)的意义。

在其它场景中,也会有一些使用意义,比如避免goto跳转,有些类似try...catch中,需要在finally中做一些统一处理,有时没有try...catch时,会采用goto来实现finally的效果,但这样代码的可读性比较差,因此可以在业务代码外面套一层do...while(0),在循环外部,做一些统一处理。

你可能感兴趣的:(C/C++,c语言,开发语言)