#define MAX(a,b) ((a)>(b)?(a):(b))
int max=MAX(x%10,y*2);
预处理之后的代码:
int max=((x%10)>(y*2)?(x%10):(y*2));
类似函数调用,把两个实参替换成宏定义中的两个形参的位置,但是函数式宏定义与真正的函数还是有很多区别:
1.函数式宏定义中的参数没有类型,预处理只负责做形式上的替换,不会去检查参数的类型,所以传参时要注意
2.编译生成的指令不同,真正的函数在编译时首先函数体要生成指令,然后每次在代码中的调用都要编译成传参指令与call调用指令,但是函数式宏定义本身不会被编译成指令,而是在每次代码调用处编程成整个函数体指令,不是简单的传参指令和call调用指令。所以用函数式宏定义生成最终的目标文件要比正常的函数生成的要大
3.函数式宏定义在调用时只是形式上的替换,但是参数或者函数体定义的a或b不一定仅仅是变量,也可能是表达式,所以要充分考虑在替换后的算术优先级,比如上例中的(a)>(b)?(a):(b)去掉括号后变成a>b,那么替换后变成x%10>y*2?x%10:y*2,优先级变了。建议:变量加括号,整体加括号。
4.考虑Side Effect情况,比如MAX(++a,++b),如果MAX是真正函数,在传入参数时,a和b只增加一次,但是如果MAX是宏定义函数,那么替换后就是((++a)>(++b)?(++a):(++b));这肯定不是我们想要的结果。
5.就算没有Side Effect,宏定义函数也会增加代码执行量,降低效率,但是它会让我们省去传参,call调用,return结果等一系列正常函数必须做的事,这也是它存在和大量使用的原因。