C语言-带参数宏定义易出现的隐藏bug和定义方式归纳

By: Ailson Jack
Date: 2021.02.26
个人博客:http://www.only2fire.com/
本文在我博客的地址是:http://www.only2fire.com/archives/129.html,排版更好,便于学习,也可以去我博客逛逛,兴许有你想要的内容呢。

宏定义尤其是带参数的宏定义,特别容易出现一些隐藏问题,因为宏定义在预处理阶段是按照定义原封不动的进行展开,此时如果展开之后涉及到运算符优先级的问题,那么隐藏bug就此出现。

这里我先列举一个简单的例子,然后归纳下带参数宏定义对于括号使用的一些说明。

1.构造带有隐藏bug的宏定义

下面定义两个带参数宏,MUL_TWO是将两个数进行相乘,MUL_THREE是将三个数进行相乘。

#define MUL_TWO(val1, val2)     (val1 * val2)

#define MUL_THREE(x, y, z)      (MUL_TWO(x, y) * z)

比如我这里计算2 * 3 * 4的运算结果,那么只需调用宏MUL_THREE(2, 3, 4)就可得到计算结果为:24,计算结果是正确的。但是如果将MUL_THREE(2, 3, 4)修改为MUL_THREE(1+1, 1+2, 1+3),此时的运算结果又是多少呢,很简单,我们将这个宏进行展开,展开的过程如下所示:

MUL_THREE(1+1, 1+2, 1+3)    => (MUL_TWO(1+1, 1+2) * 1+3)

(MUL_TWO(1+1, 1+2) * 1+3)   => ((1+1 * 1+2) * 1+3)

然后我们计算下,得出结果是7,是不是计算错误了。

2.改造上述宏定义

这里的宏定义还是比较简单的,并且大多数的小伙伴应该都知道在定义带参数的宏时,参数需要使用括号括起来,那么我们改造下上述的宏,改造结果如下所示:

#define MUL_TWO(val1, val2)     ((val1) * (val2))

#define MUL_THREE(x, y, z)      (MUL_TWO(x, y) * z)

此时再来对MUL_THREE(1+1, 1+2, 1+3)进行展开,展开的过程如下所示:

MUL_THREE(1+1, 1+2, 1+3)    => (MUL_TWO(1+1, 1+2) * 1+3)

(MUL_TWO(1+1, 1+2) * 1+3)   => (((1+1) * (1+2)) * 1+3)

然后我们计算下,得出结果是9,计算结果还是有问题。仔细检查下宏定义,原来是对MUL_THREE宏的z没有用括号括起来,这个问题也是比较容易犯的,修改好之后的宏如下所示:

#define MUL_TWO(val1, val2)     ((val1) * (val2))

#define MUL_THREE(x, y, z)      (MUL_TWO(x, y) * (z))

此时再来对MUL_THREE(1+1, 1+2, 1+3)进行展开,展开的过程如下所示:

MUL_THREE(1+1, 1+2, 1+3)    => (MUL_TWO(1+1, 1+2) * (1+3))

(MUL_TWO(1+1, 1+2) * (1+3)) => (((1+1) * (1+2)) * (1+3))

此时的计算结果就是没问题的了。

这里我再提个问题,为什么你在MUL_THREE宏中,只使用括号括起了z,为啥x和y你不同等对待,确实哈,如果对于不是很熟悉的小伙伴,可能看到我说的情况,会毫不犹豫的也对x和y进行同样的保护;也有的小伙伴看到我说的这个情况可能脑子里面就晕了。

3.带参数宏定义对于括号使用的一些说明

其实不对x和y做保护是有一个前提的,那就是你所定义的每一个宏定义都要确保对在当前宏中使用到的参数用括号进行保护。不知道各位明白我的意思不,不明白的话,看看我下面的总结吧。

带参数宏定义,对于括号何时使用的总结:

(1).带参数宏定义,如果参数在当前的宏中有进行运算,那么必须对该参数使用括号括起来(类似例子中MUL_THREE里面的z,MUL_TWO里面的val1和val2);

(2).带参数宏定义,如果参数没有在当前的宏中有进行运算,而是直接当成参数传递给其他的宏,那么该参数是不用使用括号进行保护的(类似例子中MUL_THREE里面的x和y)。

对于上面的总结第(2)点,能够对传递给其他宏的参数不进行括号保护是因为总结的第(1)点已经对宏做了一个规定,只要所有的宏定义都按照第(1)点进行书写,那么第(2)点自然也就不会出什么问题。

各位小伙伴在定义带参数的宏时,按照我上面说的2点进行书写,什么隐藏bug的也就不会存在了。

如果文中有什么问题欢迎指正,毕竟博主的水平有限。

如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^。
排版更好的内容见我博客的地址:http://www.only2fire.com/archives/129.html
注:转载请注明出处,谢谢!^_^

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jackailson

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

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

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

打赏作者

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

抵扣说明:

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

余额充值