C++ 竞赛入门
宏高级技巧
宏的高级用法与黑魔法
在 C/C++ 预处理阶段,宏(Macro)具有强大的文本替换能力。通过一些巧妙的宏定义技巧,可以实现变参处理、字符串化、连接符拼接等高级功能。
宏展开调试
要查看宏展开后的实际代码,可以使用 g++ 的 -E 选项输出预处理结果:
g++ -E 1.cpp
获取宏参数个数
通过构造一个变参辅助宏,可以利用参数位置偏移在编译期求出传入参数的个数:
#define _N_ARG_(_1, _2, _3, _4, _5, _6, N, ...) N
// 获取参数个数示例:
// 传入 7 个参数,N 对应数字 7
_N_ARG_(1, 2, 3, 4, 5, 6, 7, 8) // 展开为 7
// 传入名为 RAINBOY 的第 7 个参数
_N_ARG_(1, 2, 3, 4, 5, 6, RAINBOY, 8) // 展开为 RAINBOY
字符串化操作符 #
# 运算符用于将宏参数转换为用双引号括起来的字符串字面量:
#define STRINGIFY(x) #x
// STRINGIFY(hello) 会被替换为 "hello"
标记连接操作符 ##
## 运算符用于将两个标记(Token)连接成一个单一的标记:
#define CONCAT(a, b) a##b
// int xy = 100;
// CONCAT(x, y); 等价于访问变量 xy
可变参数宏与 ##__VA_ARGS__
__VA_ARGS__ 用于接收可变参数列表。在 GCC/Clang 等编译器中,##__VA_ARGS__ 具有特殊处理:当可变参数为空时,它会自动消除前面的逗号:
#define EACH(F, ...) (dummy, ##__VA_ARGS__)
EACH(1, 2, 3, 4, 5, 6)