宏函数以及do{...}while(0)的巧妙⽤法
宏定义,编译预处理命令,在编译预处理时即进⾏简单的字符串替换。
宏定义函数和⽤户定义的函数在使⽤时有如下区别:
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(...);
<;
if(error)
{
goto END;
}
<;
if(error)
{
goto END;
}
<;
END:
free(ptr);
return 0;
}
由于goto不符合软件⼯程的结构化,⽽且有可能使得代码难懂,所以不提倡使⽤,那这个时候就可以⽤do{}while(0)来进⾏统⼀的管理:
int foo()
{
somestruct* ptr=malloc(...);
do{
<;
if(error)
{
break;
}
<;
if(error)
{
break;
}
<;
}while(0);
free(ptr);
return 0;
}
这⾥将函数主体使⽤do{}while(0)包含起来,使⽤break来代替goto,后续的处理⼯作在while之后,就能够达到同样的效果。
三:避免空宏引起的warning
内核中由于不同架构的限制,很多时候会⽤到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使⽤
do{}while(0)来定义空宏
define的基本用法#define EMPTYMICRO do{}while(0)
四:定义⼀个单独的函数块来实现复杂的操作:
当你的功能很复杂时,变量很多你⼜不愿意增加⼀个函数的时候,使⽤do{}while(0);将你的代码写在⾥⾯,⾥⾯可以定义变量⽽不⽤考虑变量名会同函数之前或者之后的重复。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论