C语言带返回值的宏,宏函数使用{}与do{}while(0)的区别

前言        

        宏函数是在编译时进行文本替换,这样可以提高代码的执行效率,普遍用于调用比较频繁的代码段。但是需要注意一些细节。

目录

前言        

能否有返回值?

文本替代时的限制


能否有返回值?

        结论:使用{}方式允许有返回值。

        拿最简单的比较函数来举栗子,可以用如下三目运算符来写:

#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等语句后面老老实实把{}写完整来;


         分享先到这里,希望能给大家带来启发与帮助。如果对内容存在疑问或想法,欢迎在评论区留言,我会积极回复大家的问题。在我的“经验分享”专栏中,还有很多实用的经验,欢迎一起探讨、一起学习。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小星星星球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值