当前位置: 首页 > news >正文

宏定义中#与##的注意事项

1. #是字符串化操作符。它的作用是将宏参数转换成字符串

2. ##是标记粘贴操作符。它的作用是将两个标记连接起来形成一个新的标记

#define TEST1(a) #a
#define TEST2(a) b##a/***********************************************************/
举例:TEST1(hello) 会被替换为 "hello" 字符串TEST2(hello)会被替换为 bhello, 编译过程中会将bhello当作一个变量
/***********************************************************/

字符串拼接

#define HELLO_WORLD "Hello, " "World!"/***********************************************************/
在HELLO_WORLD中,"Hello, " "World!" 会被连接为 "Hello, World!"HELLO_WORLD 会被替换为 "Hello, World!" 字符串
/***********************************************************/

利用#将宏参数转换成字符串的特性可以完成字符串的拼接:

#defien HELLO(a) "hello"#a/***********************************************************/
举例:
HELLO(bye)会被替换为 "hellobye" 字符串HELLO(bye) 被转换为 "hello""bye" 再转换为 "hellobye"/***********************************************************/

重要事项

1. 在C或C++中的宏定义中,#运算符(被称为“字符串化”)只能用于宏参数。这意味着#必须直接跟在参数名称后面,不能有任何东西介于#和参数名称之间。换句话说,你不能在#和参数名之间添加任何非空白的字符。

错误案例:

#define STRING(a) nihao##a
#define TOSTRING(a) #STRING(a)/*********************************************/这个案例似乎想将nihao与参数a进行拼接并转换为字符串
但是#与参数之间不能存在其他字符,因此#操作符在此处其实是失效的
执行TOSTRING(a)等价于执行了STRING(a)
TOSTRING(a) 会被替换为 nihaoa, 编译过程中会将nihaoa当作一个变量。因为#操作符的无效/*********************************************/

2. ##符号两侧的空格会被忽略

#define CONCAT1(a,b) a##b#define CONCAT2(a,b) a  ##  b/****************************************/CONCAT1(a,b) 与 CONCAT2(a,b) 都会被替换为ab变量/****************************************/

3. ##运算符还有一个特殊的作用,就是当它跟在一个逗号后面,并且其后面继续跟随如##__VA_ARGS__的类型参数为空时,预处理器就会消除这个逗号

_VA_ARGS__ 是C语言预处理器定义的一个指示符,它代表了可变参数的列表。它主要用于宏的定义中,当你需要定义一个接收可变数量参数的宏时。

#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__ )/*****************************************************/上述宏如果被传递一个参数,例如 FOO( "Hello, world!" ),
则__VA_ARGS__为空,此时##会去掉前面的逗号,从而避免了语法错误。/******************************************************/

#__VA_ARGS__将会把__VA_ARGS__转化为字符串。


#define DEBUG(...) ##__VA_ARGS__/*********************************************/DEBUG(ni, hao, a) 会被替换为 "ni, hao, a" 字符串/**********************************************/

http://www.lryc.cn/news/309842.html

相关文章:

  • Java函数式编程
  • 【深度优先搜索】【树】【C++算法】2003. 每棵子树内缺失的最小基因值
  • 电脑开机显示器没有信号而且键盘鼠标不亮怎么解决?
  • RLWE同态加密编码打包——系数打包
  • Codeforces Round 930 (Div. 2 ABCDEF题) 视频讲解
  • 【LeetCode-中等】209.长度最小的子数组-双指针/滑动窗口
  • MACOS/LINUX/WINDOWS C++ 获取当前可执行程序的完整路径
  • 【Nginx笔记02】通过Nginx服务器转发客户端的WebSocket接口到后端服务
  • 关于高德地图及其APP获取地图数据的研究
  • 【Python入门教程】Python实现鸡兔同笼
  • 微信小程序,h5端自适应登陆方式
  • 物体检测-系列教程20:YOLOV5 源码解析10 (Model类前向传播、forward_once函数、_initialize_biases函数)
  • 贪吃蛇(C语言)步骤讲解
  • MySQL 数据库表设计和优化
  • JavaScript进阶-高阶技巧
  • C语言中“#“和“##“的用法
  • Linux命令-clock命令(用于调整 RTC 时间)
  • 编程笔记 Golang基础 045 math包
  • [Java 探索者之路] 一个大厂都在用的分布式任务调度平台
  • 基于JAVA springboot+mybatis智慧生活分享平台设计和实现
  • 详细了解C++中的namespace命名空间
  • #WEB前端(HTML属性)
  • LeetCode---【和的操作】
  • Docker容器与虚拟化技术:OpenEuler 使用 docker-compose 部署 LNMP
  • 13-微服务初探-自研微服务框架
  • LeetCode——二叉树(Java)
  • LDR6328芯片:智能家居时代的小家电充电革新者
  • 用node写后端环境运行时报错Port 3000 is already in use
  • Git 如何上传本地的所有分支
  • 【airtest】自动化入门教程(一)AirtestIDE