我们知道#define宏是一种非常暴力的替换,宏定义会在程序编译预处理阶段在调用宏的位置进行文本内容的直接替换,因此我们在使用宏定义实现Add加法函数时就要注意一些可能会报错的问题。
首先亮出答案:
#define Add(x,y) ((x)+(y))
那这里可能会有两个疑惑? 1.为什么x和y参数单独要加上括号? 2. 为什么x+y整体要加上括号?
这里是为了解决两个可能出现的问题:1.表达式问题(大括号) 2.优先级问题(小括号)
表达式冲突:
#define ADD(x,y) x+y int main() { int x = 2; int y = 3; printf("%d\n", ADD(x,y)*3 ); //宏替换为2+3*3 }
结果:
分析:我们想得到的结果应该是(2+3)*3 =15,但为什么是11呢?这里是因为宏的直接替换导致表达式为 2+3*3 =11;所以为了解决此问题我们加上大括号
优先级问题:
#define ADD(x,y) (x + y) int main() { int a = 2; int b = 3; printf("%d\n", ADD(a|b, a&b)); //宏替换为 2|3 + 2&3;算术运算符比逻辑运算符优先级高 }
结果
分析:考虑到参数可能作为表达式中的一份子,而运算符具有优先级区别,这里"+" 算术运算符比逻辑运算符"|,&"优先级更高,宏直接替换为 2|3 + 2&3 =3;所以我们为每个参数加上括号解决优先级问题
宏函数的优缺点:
优点:直接暴力替换,不是函数不需要建立函数栈帧,提高程序运行效率
可复用性
缺点:宏函数预处理阶段被替换,不会进行类型的检测,代码安全性低
宏函数不能进行调试
容易出错,宏函数的每一部分都需要加上括号
宏函数能否加分号?不可以,(如果是表达式中不小心多加了分号可以,支持两个分号同时出现 )
内联函数:填补了宏函数的缺点,继承了其优点(但是实现方式还是以空间换时间的做法)