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)