解析宏定义中的 # 运算符和 ## 运算符

学习 C 语言的都知道,# 加上一些固定的单词,可以组成预处理指令。例如:文件包括(#include)、宏定义(#define)以及条件编译(#if)等等。

同时 # 也是一个运算符,通常是用在带参数的宏定义当中。

在宏定义中 # 可以是单独出现的,也有成对出现,具体根据实际要求来进行应用。

1. # 运算符

在使用带有参数的宏的时候,有时候会遇到字符串里面的参数并没有进行替换,例如:

#include
#define SUM(A, B) printf("A+B=%d\n",(A)+(B))
int main()
{
  SUM(3, 5);
  return 0;
}

预期的打印结果是:3+5=8

但实际上的打印结果却是:A+B=8

宏相当于是占位符,在预处理阶段会将所有的宏名替换成相应替换列表里面的内容。

在替换之后,程序就变成:

#include
int main()
{
  printf("A+B=%d\n", 3+5);
  return 0;
}

那么有什么办法,可以输出预期的结果呢?

这里就要使用到 # 运算符。

#include
#define SUM(A, B) printf(#A"+"#B"=%d\n",(A)+(B))
int main()
{
  SUM(3, 5);
  // 替换后
  printf("3+5=%d\n", 3+5); 
  return 0;
}

运行之后,就可以得到预期中的结果:3+5=8

# 加上宏定义中的参数,相当于给这个参数内容加上一个双引号。在预处理阶段,会将#A转换为"A"。

#include
#define PrintStr(A) printf(#A)
int main()
{
  PrintStr(你好,C语言\n再见,C语言);
  return 0;
}

运行结果:

另外,再提一个小知识点:在 printf 函数中,只要不在字符串末尾加上逗号,放再多对的双引号,也都会被组合在一起。一旦用逗号隔开了,除非在前面有格式符号占位,否则只会输出逗号前面的所有字符串内容。

#include
int main()
{
  printf("黑化肥""发灰""会挥发","abc");
  return 0;
}

运行结果:黑化肥发灰会挥发

2. ## 运算符

和 # 运算符一样,## 运算符同样是作用在带参宏里,也是在预处理阶段就完成替换。

其作用是将两个记号组合成一个记号,例如:

#include
#define XNAME(N) x##N
int main()
{
  int x1=3, x2=5, x3=8;
  printf("%d+%d=%d\n", XNAME(1), XNAME(2), XNAME(3));
  return 0;
}

此时 XNAME(1) 就相当于 x1。

运行后可得到打印结果:3+5=8

看到这里,# 运算符好歹有些作用,但## 运算符好像并没有给我们带来什么便利,反而让简单的事情变得更复杂了。

不过 ## 运算符既然存在,那么就一定有它存在的意义。在一定程度上可以提高封装性和程序的可读性。

例如,许多 C 语言有些外部依赖项文件也会应用到 ## 运算符。

concurrencysal.h 部分代码

corecrt.h 部分代码

解析宏定义中的 # 运算符和 ## 运算符_第1张图片

大多数都是非常长的,如果每次都要编写,就需要浪费大把的时间去校准拼写有没有错误。

## 运算符作为一个优秀的粘合剂,则可以让我们无需去记住那些共同部分,只需要填写不同的内容即可。

最后

关于 # 运算符和 ## 运算符的笔记就到这里结束了,如有发现错误,欢迎留言指出。

如果您觉得本篇文章还可以,点个赞支持一下呗!

你可能感兴趣的:(C语言学习,c语言,学习,开发语言)