宏函数

  • 宏函数类似于函数,包含函数名、参数和实现,与函数定义差别不大(没有返回值和大括号)
    • 可视情况决定函数结尾是否添加分号
1
2
3
4
5
6
7
// 定义一个宏函数,实现三数相加
#define SUM(a, b, c) a + b + c

// 使用这个函数
int k = SUM(1, 2, 5) + 6;
// 等价于
int k = 1 + 2 + 5 + 6;
  • 也可以将宏函数的参数作为函数名或类名使用
1
2
3
4
5
#define STRINGPARAM(func, string) func(string)

STRINGPARAM(std::printf, "Hello, World!");
// 等价于
std::printf("Hello, World!");
  • 甚至可以将宏函数的参数作为宏名使用
1
2
3
4
5
6
7
8
// 先定义一个宏
#define VECTOR(type, name) std::vector<type> name
// 再定义一个宏
#define DATACONTAINER(container_type) container_type(int, A); container_type(std::string, B);

DATACONTAINER(VECTOR)
// 等价于
std::vector<int> A; std::vector<std::string> B;
  • 是的,宏函数也可以接受数量可变的参数:只需要配合使用...__VA_ARGS__即可
1
2
3
4
5
6
// 定义宏
#define OUTPUT(...) std::printf(__VA_ARGS__)

OUTPUT("%d: %d", num1, num2);
// 等价于
std::printf("%d: %d", num1, num2);
  • 可变参数可以放在固定参数后面
1
2
3
4
5
6
// 定义宏
#define NEWARRAY(type, size, name, ...) std::array<type, size> name = { __VA_ARGS__ }

NEWARRAY(int, 10, data, 1, 2, 3, 4);
// 等价于
std::array<int, 10> data = { 1, 2, 3, 4 };
  • 特殊符号:#,字符串化
    • #abc会被翻译为"abc"
1
2
3
4
5
6
7
// 定义宏
#define OUTPUT(var) std::cout << #var << " " << var << std::endl

int k = 10;
OUTPUT(k);
// 等价于
std::cout << "k" << " " << k << std::endl;
  • 特殊符号:##,token粘贴(标记粘贴)
    • A##B会被转换为AB,此后AB可以作为其他宏名/变量名等进行替换
1
2
3
4
5
#define ARRAYS(type, size, name) std::array<type, size> name##_dbg, name##_rel

ARRAYS(int, 10, data);
// 等价于
std::array<int, 10> data_dbg, data_rel;
  • __VA_ARGS__也支持特殊符号,即#__VA_ARGS__##__VA_ARGS__
  • 宏与其定义顺序无关;但为保证可读性,还是建议位于文件上方的宏不要依赖文件下方的宏
  • 宏函数无需写到一行内,复杂的宏可以通过\分割为多行
    • 注意:\必须是行内的最后一个字符,即使是后面多了一个空格也不行
    • 注意:给多行的宏函数内添加注释只能使用/* */
1
2
3
4
5
6
#define CHECK_REGULATORY(a, b, res) \
/* Threshold is 100 */ \
if (a > 100 || b > 100 || a < 0 || b < 0) \
res = false; \
else \
res = true;
评论