C宏中的##(token pasting)
C宏中的##(token pasting)
以下内容来自GPT
在 C 和 C++ 中,##
运算符称为“token pasting”运算符或“粘贴”运算符,用于宏定义中。当使用 ##
运算符时,它会将前后的标记(token)直接拼接在一起。在 __VA_ARGS__
前面使用 ##
运算符有一个特定的用途,主要是在处理变参宏时避免多余的逗号。
作用解释:
在变参宏中,如果你使用 __VA_ARGS__
并且调用宏时没有传递任何可变参数,那么会出现一个多余的逗号,导致语法错误或不期望的行为。例如:
#define DEBUG_LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
假设你这样调用宏:
DEBUG_LOG("A message");
展开后会变成:
fprintf(stderr, "A message", );
这会在 fprintf
函数调用中留下一个多余的逗号,导致编译错误。
为了防止这种情况,使用 ##__VA_ARGS__
来自动去掉这个多余的逗号。
示例:
#define DEBUG_LOG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
当 __VA_ARGS__
是空的时候,##
会将前面的逗号自动移除。例如:
-
有可变参数:
DEBUG_LOG("Value: %d", 42);
展开后:
fprintf(stderr, "Value: %d", 42);
-
没有可变参数:
DEBUG_LOG("A message");
展开后:
fprintf(stderr, "A message");
在这种情况下,##__VA_ARGS__
确保即使没有传递可变参数,宏的展开依然是合法的,不会留下多余的逗号。
总结:
##__VA_ARGS__
的主要作用是在变参宏中,当 __VA_ARGS__
为空时,自动去掉前面的逗号,确保宏的展开结果是有效的 C/C++ 代码。
注意事项
如果用##来连接字符串,那么要注意:这个连接操作发生在宏展开之前。