C语言中宏定义中#和##之我见以及其在嵌入式中的简单运用

宏命令里,有许多细节知识点,用得好,可以给对代码质量有更高的改善,本文主要是讲述#和##两个预处理运算符的作用和使用做了简单的阐述,并列举了一个在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初始化*/    
}

从上面可以看出,简单的宏命令,可以写出高质量(效率高、可移植性、可读性好)的代码。。

——————————————————
目前就用到这一个,后面遇到高级应用,再添加…

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值