探索#和##的用法已经限制

华丽的开头:

在一些开源的软件中经常出现#和##得用法, 因此搞清楚其语意就变得很重要,尤其是一些C语言功底并不是那么扎实的童鞋来说(比如我)。其实#和##的作用可以统一用一句话来概括,"使得变量的组织和运用变得更加灵活", 有些读者可能刚开始无法理解,没关系,通过本文,相信您对#和##一定有一个深入的认识。好了,进入正题。

 

#的用法

解释:一般#是将右侧宏参数格式化为一个字符串

实例1:

#define T(X)    #X
int main(void)
{
    printf("T(x):\"%s\"\r\n", T(A));
    printf("T(x):\"%s\"\r\n", T("A"));
    printf("T(x):\"%s\"\r\n", T('A'));
    while (true);
    return 0;
}

大家猜猜打印的结果是什么,此处冥想10秒钟。。。。。。如下

其输出结果为

可以看出 :不管A是字符串 或者是 数字 再或者 没有定义, #X的结果都将是将X转换为字符串"X"

哪有的人就要问了,要是A被定义了,但是A是一个宏,那还会不会如上一样直接转换为"A"呢? 我们继续实验

实验2

#define  A         129
#define T(X)       #X
int main(void)
{
    printf("T(x):\"%s\"\r\n", T(A));
    while (true);
    return 0;
}

这次的结果

我们可以看到,结果依旧是"A",而不是"129" ,这是不是说明#在做宏展开的时候并不会展开其内部的宏参数呢。然而并不是都是这样,这仅仅局限于一次宏展开。

实例3

#define A          (129)
#define T(X)       #X
#define TT(X)      T(X)
int main(void)
{
    printf("T(x):\"%s\"\r\n", TT(A));
    while (true);
    return 0;
}

按上面的结论,此时结果应该依旧是"A",然而并不是这么简单的。

这是为什么呢?让我们来看一看预编译时的宏展开过程。

TT(A) --->   T(A)  ---->  T((129))  ---> #(129) --> "(129)"

T(A)   ----   #A   ---- > "A"

此时我们可以得出结论:

     #只会将宏参数直接格式化为字符串,如果一级展开发现其含有# 那么此时将不会对宏进行展开,直接转为字符串,如果不存在且其实参任然是宏参数,则对内部宏参数进行替换。

 

##的用法

解释:##一般用来连接两个特定的对象,并组成一个新的字符串或者变量,也就是将两个对象粘合在一次。

大家是不是看到这个解释都被绕迷糊了,没关系,下面会给出一些简单的实例代码进行解释。

实例1:

#define GPIOA    0X10
#define RCC_APB2Periph_GPIOA  0X0101
#define RCC_CLK(X)   RCC_APB2Periph_##X

int main(void)
{
    printf("0X%X\r\n", RCC_CLK(GPIOA));
    while (1);
    return 0;
}

相信大家都猜到了结果,没错 结果就是0X0101,这说明##的参数格式化过程中同样不存在参数的展开,如果结果必然无法运行通过,因为其试图打印RCC_APB2Periph_0X10,这显然是错误的。

同样,按照上面的思维,因为##处在以及宏展开的位置,是不是由于这个原因导致的宏参数没有被展开呢?带着这样的疑惑,我们继续进行探索实验。

实例2

#include <stdio.h>

#define GPIOA                 0X10
#define RCC_APB2Periph_GPIOA  0X0101
#define RCC_CLK(X)            RCC_APB2Periph_##X
#define RCC_CLK_COPY(X)       RCC_CLK(X)
int main(void)
{
    printf("0X%X\r\n", RCC_CLK_COPY(GPIOA));
    while (1);
    return 0;
}

猜测:

1、如果宏参数一直不会展开,那么此时打印的结果应该与上面的一样  为0X0101

2、如果宏参数展开了,那么此时必定是报RCC_APB2Periph_0X10未定义什么的

好了  我们直接看结果

结果完全符合了猜想2,因此我们得出以下结论。

结论

   进行宏操作的时候,如果一级宏展开遇到#或者##,那么即使此时的实参任然是宏参数也不会进行宏展开,而是直接进行(#格式化为字符串,##直接连接到其他部分)操作,否则,将依次对内部宏参数进行展开

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值