宏命令里,有许多细节知识点,用得好,可以给对代码质量有更高的改善,本文主要是讲述#和##两个预处理运算符的作用和使用做了简单的阐述,并列举了一个在MSP430单片机上的一个简单的应用。
1.预处理运算符:“#”(字符串化)
#符的作用:把传递过来的参数当成字符串进行替代,即先将#符右边参数进行宏替换,再加双引号引起来,将参数字符串化。(直观描述)
#include <stdio.h>
#define TEST(x) puts("This is test"#x)
int main()
{
TEST(1); /*等价于puts("This is test1"); */
TEST(10);/*等价于puts("This is test10");*/
return 0;
}
执行结果:
This is test1
This is test10
第一次调用#x被替换成了“1”,第二次调用时#x被替换成了“10”。
专业解释:在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转化成字符串。例如,如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing)。
2.预处理运算符:“##”(连接字符串)
##的作用:它是一个连接符号,用于把参数连在一起,先分隔字符替换,再强制连接,即先将替换序列分隔(分隔的作用类似插入空格),再进行宏替换,最后将替换后的序列强制连接(去掉前面的字符串之间的空格)。
#include <stdio.h>
#define A1(name, type) type name_##type##_type
#define A2(name, type) type name##_##type##_type
int main()
{
A1(a1, int); /* 等价于: int name_int_type; */
A2(a1, int); /* 等价于: int a1_int_type"; */
return 0;
}
执行结果解释:
1) 在第一个宏定义中,”name”和第一个””之间,以及第2个””和第二个 ”type”之间没有被分隔,所以预处理器会把name_##type##type解释成3段:“name”、“type”、以及“_type”,这中间只有“type”是在宏前面出现过 的,所以它可以被宏替换。
2) 而在第二个宏定义中,“name”和第一个“”之间也被分隔了,所以 预处理器会把name####type##type解释成4段:“name”、“”、“type”以及“_type”,这其间,就有两个可以被宏替换了。
3) A1和A2的定义也可以如下:
#define A1(name, type) type name_ ##type ##_type
<##前面随意加上一些空格>
#define A2(name, type) type name ##_ ##type ##_type
结果是## 会把前面的空格去掉完成强连接,得到和上面结果相同的宏定义
3. “#” 和 “##” 在嵌入式中的简单运用
有时候,为了简化函数的书写,简单的宏命令能写出高质量的代码。
比如MSP430单片机,在进行配置的时候,每个引脚都需要配置其功能选择寄存器PxSEL、方向寄存器PxDIR、数据寄存器PxDAT,中间的x就是引脚组数。
比如MSP430单片机引脚P1.5、P1.6、P1.7分别连接着LED1,LED2,LED3灯,低电平点亮,普通的做法是:
void Led_Init()
{
/*初始化LED1*/
P1SEL &=~BIT5;
P1DIR |=BIT5;
P1DAT &=~BIT5;
/*初始化LED2*/
P1SEL &=~BIT6;
P1DIR |=BIT6;
P1DAT &=~BIT6;
/*初始化LED3*/
P1SEL &=~BIT7;
P1DIR |=BIT7;
P1DAT &=~BIT7;
}
通过上面代码可以看出,重复代码比较多,而且不利于后期移植和后期维护,而只要通过简单的宏命令,即可实现简单的高质量的初始化代码。
#define Port_Init(group,num,data)\
do{\
P##group##SEL &=~BIT##num;\
P##group##DIR |=BIT##num;\
P##group##DAT |=(data<<num);\
}while(0)
void Led_Init()
{
Port_Init(1,5,0);/*LED1初始化*/
Port_Init(1,6,0);/*LED2初始化*/
Port_Init(1,7,0);/*LED3初始化*/
}
从上面可以看出,简单的宏命令,可以写出高质量(效率高、可移植性、可读性好)的代码。。
——————————————————
目前就用到这一个,后面遇到高级应用,再添加…