带参数的宏定义不是简单的字符串替换,还要进行参数替换。一般格式如下:
#define 宏名(参数表)字符串
程序举例: 对两个数实现乘法、加法混合运算。
#include <stdio.h>
#define MIX(a,b) ((a)*(b) + (b))
int main(void) {
int x = 5, y = 9;
printf("x, y:\n");
printf("%d, %d\n", x, y);
printf("The min number is:%d\n", MIX(x,y));
return 0;
}
程序运行结果为:
x, y:
5, 9
The min number is:54
当编译该程序时,由MIX(a, b)定义的表达式被替换,x 和 y 用作操作数,即printf()语句被代换
后成为如下形式。
printf("this min number is: %d", ((a)*(b) + (b)));
用宏替换代替实际的函数的一个好处是宏替换增加了代码的执行速度,因为不存在函数调用;但增加速度也有代价
--由于重复编码而增加了程序长度。
对于带参数的宏定义有以下几点需要强调:
1)宏定义时参数要加括号,如不加括号,有时结果是正确的,有时结果却是错误的。
#define MIX(a,b) (a*b + b)
例如,上面的例子中,当参数x = 10, y = 9时,在参数不加括号的情况下调用MIX(x,y),可以正确地输出结果,但是
当参数x = 10, y = 6 + 3时,在参数不加括号的情况下调用MIX(x,y),此时的输出结果是错误的,因为此时调用的
MIX(x, y)执行情况为:
(10*6+3+6+3)
结果为72,实际想要的结果为10*(6 + 3) = 90
为了避免出现以上情况,需要在进行宏定义时在参数外面加上括号。
2)宏扩展必须使用括号,来保护表达式中低优先级的操作符,以便确保调用时达到想要的效果。
#define MIX(a,b) (a)*(b) + (b)
如将宏定义改成以上形式,则调用:
5*MIX(a,b)
会被扩展成:
5*(a)*(b)+(b)
本意是想扩展成:
5*((a)*(b)+(b))
解决的办法就是上面说的宏扩展时加上括号,这样就能避免这种错误的发生。
注意点:
1)对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替#define 命令行
中的形参。
2)在宏定义时,在宏名与带参数的括号之间不可以加空格,否则会将空格以后的字符都作为
替换字符串的一部分。
3)在带参数的宏定义中,形式参数不分配内存单元,因此不必做类型定义。
使用宏定义的好处:
(1)输入代码时可以省去许多输入操作因为宏名要比宏体短。
(2)因为宏只需要定义一次,可以多次使用,而定义的宏名往往有一定的含义,所以使用宏能
增强程序的易读性和可靠性。
(3)宏不会引起额外的开销。宏的代码只会在宏出现的地方展开,不会引起程序的跳转,可以节省
程序调用的时间。
(4)宏的参数对类型不敏感,因此不用过多考虑参数的类型问题。