前言
宏函数是在编译时进行文本替换,这样可以提高代码的执行效率,普遍用于调用比较频繁的代码段。但是需要注意一些细节。
目录
能否有返回值?
结论:使用{}方式允许有返回值。
拿最简单的比较函数来举栗子,可以用如下三目运算符来写:
#define COMPARE(x, y) ((x)>(y))?(x):(y)
/*示例*/
void test(void)
{
int tempVal_1 = 6;
int tempVal_2 = 7;
printf("最大值为:%d", COMPARE(tempVal_1 , tempVal_2));
}
也可以用if语句来写:
#define COMPARE(x, y, type) ({ \
typeof(type) _tempCompareVal_; \
if((x)>(y)) \
{ \
_tempCompareVal_ = x; \
} \
else \
{ \
_tempCompareVal_ = y; \
} \
_tempCompareVal_; \
})
/*示例*/
void test(void)
{
int tempVal_1 = 6;
int tempVal_2 = 7;
float tempVal_3 = 6.6;
float tempVal_4 = 7.7;
printf("最大值为:%d\n", COMPARE(tempVal_1 , tempVal_2, int));
printf("最大值为:%d\n", COMPARE(tempVal_3 , tempVal_4, float));
}
细心的同学可以看到在{}外加了()。首先使用{}把代码块作为一个整体,接着用()把该整体表达式化就可以返回整体里的最后一个语句的值,即"_tempCompareVal_"的值。至于typeof的用法,简单理解就获取类型,宏里的"type"可以是变量、类型、表达式,如果想深入理解可以去百度补习一下。
文本替代时的限制
结论:在使用if、for等语句时,某些时候使用{}方式会非法,而只能使用do{}while(0)方式。
当if等语句后使用宏函数且没有加对应的"{}"时,使用{}方式时为何非法?请看下面的栗子:
#define FUNC_1() { Set_GPIO_UP(); Set_GPIO_DOWN(); } /**< {}方法 */
/*******使用{}方法*******/
if(true)
FUNC_1(); /* 非法 */
else
xxxx;
//文本替换后如下:
if(true)
{
Set_GPIO_UP();
Set_GPIO_DOWN();
}; /* 注意这里的";" */
else
xxxx;
//原因分析:文本替换后,";"为if语句的结束符,导致if else语句被分隔,使其非法。
/*******使用{}方法 End*******/
使用do{}while(0)方式合法:
#define FUNC_2() do{ Set_GPIO_UP(); Set_GPIO_DOWN(); }while(0) /**< do{}while(0)方法,切记不要宏函数里最后加“;” */
/*******使用do{}while(0)方法*******/
if(true)
FUNC_2(); /* 合法 */
else
xxxx;
//文本替换后如下:
if(true)
do \
{ \
Set_GPIO_UP(); \
Set_GPIO_DOWN(); \
}while(0); /* 这里的";"为do{}while(0)语句的结束符 */
else
xxxx;
/*******使用do{}while(0)方法 End*******/
当if语句后跟上"{}",则两种方式都是合法的:
#define FUNC_1() { Set_GPIO_UP(); Set_GPIO_DOWN(); } /**< {}方法 */
#define FUNC_2() do{ Set_GPIO_UP(); Set_GPIO_DOWN(); }while(0) /**< do{}while(0)方法,切记不要宏函数里最后加“;” */
/*示例*/
if(ture)
{
FUNC_1(); /* {}方法 合法 */
}
if(ture)
{
FUNC_2(); /* do{}while(0)方法 合法 */
}
终上所述,所以我在日常开发时会考虑宏函数是否需要返回值,如果不需要返回值则统一选择do{}while(0)方式,如果需要返回值则统一选择{}外加()方式即({...});
还有就是if,for等语句后面老老实实把{}写完整来;
分享先到这里,希望能给大家带来启发与帮助。如果对内容存在疑问或想法,欢迎在评论区留言,我会积极回复大家的问题。在我的“经验分享”专栏中,还有很多实用的经验,欢迎一起探讨、一起学习。