带参数的宏定义
宏定义不是进行简单的字符串替换,还要进行参数替换。其定义的一般形式为:
#define 宏名(参数表) 字符串
字符串中包含在括弧中所指定的参数。如:
#define sbi(Y,X) Y |= (1 << X)
...
sbi(P0,2);
//实现对P0口P0.2位置1
宏展会后
P0 |= (1 << 2);
使用参数宏的几个注意事项
1.对带参数的宏的展开只是将语句中的宏名后面括号内的实参字符串代替#define命令中的行参。
2.在宏定义时,在宏名与带参数的括弧之间不应加空格,否则将空格以后的字符都作为代替字符串的一部分。
#define sbit (Y,X) Y |= (1 << X)
...
sbit(P0,2);
宏展开后
(Y,X) Y|= (1<<X)(P0,2);
显然不对。
参数宏与函数的联系与区别
1.函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换。例如:sbi(P0,a+b),在宏展开时并不求a+b的值,而只讲实参字符"a+b"代替形参Y。
2.函数调用是在程序运行时处理的,分配临时的内存单元。而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。
3.对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换。而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符合代表,展开时代入指定的字符即可。宏定义时,字符串可以是任何类型的数据。
4.宏替换不占运行时间,只占编译时间。而函数调用则占用运行时间(分配单元、保留现场、值传递、返回)。