文章目录

  • 1 # 运算符
    • 1.1 # 运算符的基本用法
    • 1.2 # 运算符的妙用
  • 2 ## 运算符
    • 2.1 ##运算符的基本用法
    • 2.2 ##运算符的工程运用
  • 3 总结

1 # 运算符

  • #运算符用于在预处理期将宏参数转换为字符串
  • #的转换是在预处理期间完成的,因此,只在宏定义中有效
  • 编译器并不知道 # 的转换作用
  • 用法如下:

1.1 # 运算符的基本用法

  • 代码:25-1.c
#include <stdio.h>#define STRING(x) #xint main()
{printf("%s\n", STRING(Hello world!));printf("%s\n", STRING(100));printf("%s\n", STRING(while));printf("%s\n", STRING(return));return 0;
}
  • 运行结果如下:

  • 结果显而易见,这种用法也是非常的简单易懂。不多做说明。

1.2 # 运算符的妙用

如果想在调用函数的时候讲函数自动打印,好让我们更加了解程序的执行流程。那么我们可以使用 # 运算符来实现这个功能。

如下面的代码:

  • 25-2-lyy.c
#include <stdio.h>#define CALL(f, p) (printf("Call function %s\n", #f), f(p))int square(int n){return n*n;
}int func(int x){return x;
}
int main(){int result = 0;result = CALL(square, 4);printf("result = %d\n", result);result = CALL(func, 20);printf("result = %d\n", result);return 0;
}
  • 编译运行上述代码结果如下:

代码很简单,结果也很简单。不多做分析。只需要注意 # 运算符的作用即可

2 ## 运算符

  • ##运算符用于在预处理期粘连两个标识符
  • ##的连接是在预处理期完成的,因此只在宏定义中有效
  • 编译器不知道 ## 的作用
  • 用法如下:

2.1 ##运算符的基本用法

  • 代码25-3.c
#include <stdio.h>#define NAME(n) name##nint main()
{int NAME(1);int NAME(2);NAME(1) = 1;NAME(2) = 2;printf("%d\n", NAME(1));printf("%d\n", NAME(2));return 0;
}
  • 编译运行结果为:

  • 上述代码也比较简单,学会使用##运算符即可

2.2 ##运算符的工程运用

如下代码:

25-4.c

#include <stdio.h>typedef struct _tag_Student Student;
struct _tag_Student
{char* name;int id;
};
int main()
{Student s1;Student s2;s1.name = "s1";s1.id = 0;s2.name = "s2";s2.id = 1;printf("s1.name = %s\n", s1.name);printf("s1.id = %d\n", s1.id);printf("s2.name = %s\n", s2.name);printf("s2.id = %d\n", s2.id);return 0;}

上面的代码,没有任何问题,但是如果需要定义多个结构体,那么每次都要将下面样式的代码下一遍:

typedef struct _tag_Student Student;
struct _tag_Student
{char* name;int id;
};

这是非常繁琐的。

但是如果我们使用##运算符,写出下面的代码,就会方便很多:

  • 25-4-lyy.c
#include <stdio.h>#define STRUCT(type) typedef struct _tag_##type type;\struct _tag_##typeSTRUCT(Student)
{char* name;int id;
};int main()
{Student s1;Student s2;s1.name = "s1";s1.id = 0;s2.name = "s2";s2.id = 1;printf("s1.name = %s\n", s1.name);printf("s1.id = %d\n", s1.id);printf("s2.name = %s\n", s2.name);printf("s2.id = %d\n", s2.id);return 0;
}

上面两个代码的编译运行结果是一样的:

但是很明显,25-4-lyy.c 比25-4.c更加简洁通用以下。这就是##运算符的妙用。

3 总结

  • #运算符用于在预处理期将红参数转换为字符串
  • ##运算符用于在预处理期粘连两个标识符
  • 只有预处理器知道#和##的存在,编译器并不知道
  • #和##只在宏定义中有效

【C语言进阶深度学习记录】二十一 # 和 ## 号操作符的使用与分析相关推荐

  1. 【C语言进阶深度学习记录】九 C语言中const的详细分析

    文章目录 1 const的分析 2 const本质的分析实验 2.1 代码案例分析 3 const修饰函数参数和返回值时的情况 3.1 代码案例分析 4 总结 1 const的分析 不管是C语言还是C ...

  2. 【C语言进阶深度学习记录】十一 C语言中enum,sizeof,typedef分析

    文章目录 1 enum 枚举类型的使用方法 1.1 enum枚举类型的特殊意义 1.2 代码分析:enum的使用 2 sizeof 关键字的用法 2.1 代码案例分析:sizeof的本质 3 type ...

  3. 【C语言进阶深度学习记录】二十六 C语言中的字符串与字符数组的详细分析

    之前有一篇文章是学习了字符和字符串的,可以与之结合学习:[C语言进阶深度学习记录]十二 C语言中的:字符和字符串 文章目录 1 字符串的概念 1.1 字符串与字符数组 1.2 字符数组与字符串代码分析 ...

  4. 【C语言进阶深度学习记录】三十五 程序中的堆、栈以及静态存储区(数据区)

    学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 在我之前学习底层的知识的时候,也写过相关的内容.可以对比的学习:[软 ...

  5. 【C语言进阶深度学习记录】三十八 C/C++语言中的函数声明与函数定义

    文章目录 1 函数的声明和定义 1.1 代码分析 2 总结 1 函数的声明和定义 声明的意义在于告诉编译器程序单元的存在.只是告诉编译器它存在但是不在声明这里定义,有可能在当前文件中的其他地方或者其他 ...

  6. 【C语言进阶深度学习记录】十九 #pragma使用与分析

    文章目录 1 #pragma 概念简介 1.1 #pragma message 的用法 1.2 #pragma once 的用法 1.3 #pragma pack 的用法 1.31 struct占用的 ...

  7. 【C语言进阶深度学习记录】十六 静态库与动态库的创建与使用

    上一篇文章学习了编译的过程,点击链接查看:[C语言进阶深度学习记录]十五 编译过程简介,每一个C源文件编译后将会生成目标文件,那么这些目标文件,还需要链接起来,生成可执行文件. 文章目录 1 链接的意 ...

  8. 【C语言进阶深度学习记录】八 C语言中void的分析

    文章目录 1 void的意义 1.1 不存在void变量 1.2 C标准 1.3 void指针的意义 1.4 通过void* 实现memset函数 2 总结 1 void的意义 void修饰函数的参数 ...

  9. 【C语言进阶深度学习记录】五 C语言中变量的属性

    上一篇文章学习了C语言中的类型转换,点击链接查看:[C语言进阶深度学习记录]四 C语言中的类型转换. 文章目录 1 C语言的变量属性 1.1 auto关键字 1.2 register关键字 1.3 s ...

  10. 【C语言进阶深度学习记录】三十 二维数组与二维指针

    文章目录 1 二维指针(指向指针的指针) 2 二维数组 3 二维数组的类型 3.2 如何动态申请二维数组 4 总结 1 二维指针(指向指针的指针) 指针的本质是变量 指针的指针是保存指针变量的地址.如 ...

最新文章

  1. Java报告比较日期_Java程序如果一个日期在另一个日期之后比较日期
  2. 【JavaScript吉光片羽】遭遇IE8
  3. Windows下打包maven项目,编写bat脚本,dos命令在后台运行与关闭
  4. 计算机导论中IEE是什么缩写,Proc.IEE是期刊吗?全称是什么
  5. 面试题3:二维数组查找
  6. 牛客网【每日一题】 合集
  7. 升级鸿蒙系统无法选择应用,申请鸿蒙系统有一个应用选择怎么选择呢
  8. 智慧教室解决方案和移动授课概念说明
  9. 【机器视觉】常见机器视觉软件及选型要点分析
  10. 使用OVF部署虚拟机
  11. 分裂对象模型和TclCL(2)
  12. mysql存储过程 begin_MySQL存储过程的BEGIN和END
  13. 极客大学架构师训练营 编程的本质与未来 第三课 听课总结
  14. 64行代码实现简单人脸识别
  15. Android--分享功能
  16. 超酷,用 Python 教你绘制皮卡丘和哆啦A梦
  17. 形形色色的Linux 发行版代号都在这里
  18. 事业公共基础计算机,2011安徽省事业编公共基础知识(必备资料)
  19. [置顶]使用scrapy_redis,自动实时增量更新东方头条网全站新闻
  20. rk3328 rk3399使用fbtft驱动SPI LCD显示

热门文章

  1. 实例5:python
  2. solor mysql_solr 同步 mysql
  3. mysql受影响的行 0_为什么更新/删除成功时受影响的行返回0?
  4. 非会员只能试看20分钟_做欧包都要把铁锅烤半小时?太费电了,用我这办法只需预热几分钟...
  5. activiti高亮显示图片_【正点原子FPGA连载】第二十章SD卡读BMP图片HDMI显示实验领航者 ZYNQ 之嵌入式开发指南...
  6. bzoj 3173 最长上升子序列
  7. URAL1553 Caves and Tunnels 树链剖分 动态树
  8. 军训分批(codevs 2751)
  9. android studio -genymotion神奇错误
  10. 【编程题目】给你 10 分钟时间,根据上排给出十个数,在其下排填出对应的十个数...