宏定义中的#和##
参考:https://mazhuang.org/2014/05/10/numbersign/#标记连接操作-
说明
- C/C++ 中# 和 ## 符号用于宏定义;
- # 作用是将宏定义参数不经任何扩展地转换成字符串常量,所谓拓展包括:
- 宏定义参数的两边的空格会被忽略;
- 特殊字符会被加上转义字符;
- ## 的作用是在宏定义中,将两个部分连接成一个部分,需要注意:
- 用于连接,所以不能用在首尾;
- 其前后的空格无意义;
示例
知识点准备:
下面四组其实是等价的:
char* p1 = "Hello," "World!"; // 一个空格
char* p2 = "Hello," "World!"; // 多个空格
char* p3 = "Hello,""World!"; // 没有空格
char* p4 = "Hello,World!"; // 一个整串
字符化操作(#)
以MSDN上的例子说明:
#define F abc
#define B def
#define FB(arg) #arg
#define FB1(arg) FB(arg)
qDebug()<<FB(F B);
qDebug()<<FB1(F B);
乍一看,两个输出应该是一样的,其实不然,这里的 # 操作符起作用的时间不一样,实际输出是:
F B
abc def
宏定义在调用时就进行字符串的替换,这里的所谓的不经扩展 就是直接替换,所以,上例中的替换步骤是:
FB(F B) => #F B => "F B"
FB1(F B) => FB(abc def) => #abc def => "abc def"
标记连接操作(##)
以MSDN上的例子说明
#define paster( n ) printf_s( "token" #n " = %d", token##n )
int token9 = 8;//这里例子里是9,我为了区分,改成了8
paster(9);
最后的输出结果是:
token9 = 8
在编译的时候,宏定义替换字符串步骤如下:
paster(9)
printf_s( "token" #9 " = %d", token##9 )
printf_s( "token" "9" " = %d", token9 )
printf_s( "token9" " = %d", token9 )
__VA_ARGS__
__VA_ARGS__ 是一个可变参数宏,在宏中传递参数时,它可以表示传递的 ...,示例如下:
#define test(...) qDebug(__VA_ARGS__)
test(1, 2, 3) //这里的参数至少有一个
这里有个问题就是,可变参数至少有一个,因为当参数一个都没有时,有个 ,
会导致编译错误
##__VA_ARGS__ 可以解决至少有一个参数的问题,其作用是,当参数数目为0时,去掉前面的逗号
#define test(...) qDebug(##__VA_ARGS__)
test() //这里的不传参也可以
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步