宏函数以及do{...}while(0)的巧妙用法

2023-05-16

宏定义,编译预处理命令,在编译预处理时即进行简单的字符串替换。
宏定义函数和用户定义的函数在使用时有如下区别:
1、宏函数会在编译预处理时展开,只占用编译时间,函数调用则会占用运行时间(分配单元、保存现场、值传递、返回等),每次执行都需要载入,所以执行相对于宏较慢。
2、在函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换。
3、函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有返回值的概念。
4、对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型的问题,宏名无类型,只是一个符号代表,展开时代入指定的字符即可。宏定义时,字符串可以是任意类型的数据。
5、宏函数的定义也有缺点,它容易会产生二义性。

do
{

}while(0)的巧妙用法
一:在宏函数中使用do{…}while(0),辅助定义复杂的宏,避免引用的时候出错

#define DOSOMETHING() \
do \
{ \
	fool1(); \
	fool2(); \
}while(0) \

二:避免使用goto,实现对程序流程进行统一的控制。
有些函数中,在renturn之前我们经常会进行一些收尾的工作,比如free掉一块函数开始malloc的内存,goto一直是一个比较简单的方法:

int foo()
{
	somestruct* ptr=malloc(...);
	dosomething...;
	if(error)
	{
		goto END;
	}
	dosomething...;
	if(error)
	{
		goto END;
	}
	dosomething...;
END:
	free(ptr);
	return 0;
}

由于goto不符合软件工程的结构化,而且有可能使得代码难懂,所以不提倡使用,那这个时候就可以用do{}while(0)来进行统一的管理:

int foo()
{
	somestruct* ptr=malloc(...);
	do{
		dosomething...;
		if(error)
		{
			break;
		}
		dosomething...;
		if(error)
		{
			break;
		}
		dosomething...;
	}while(0);
	free(ptr);
	return 0;
}

这里将函数主体使用do{}while(0)包含起来,使用break来代替goto,后续的处理工作在while之后,就能够达到同样的效果。

三:避免空宏引起的warning
内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏

#define EMPTYMICRO do{}while(0)

四:定义一个单独的函数块来实现复杂的操作:
当你的功能很复杂时,变量很多你又不愿意增加一个函数的时候,使用do{}while(0);将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

宏函数以及do{...}while(0)的巧妙用法 的相关文章

随机推荐