宏的高级技巧
宏的高级技巧包括可变参数、字符串化、标记连接、条件表达式等。这些技巧可以实现更灵活的代码生成,但也增加了复杂性和出错概率。理解这些技巧,可以在必要时写出强大的宏,但应谨慎使用。
可变参数宏(C99)
#define LOG(fmt, ...) printf("[LOG] " fmt "\n", __VA_ARGS__)
LOG("Value: %d", 42); /* [LOG] Value: 42 */
LOG("Error"); /* 错误:__VA_ARGS__ 为空 */
/* C99 技巧:##__VA_ARGS__ 处理空参数 */
#define LOG2(fmt, ...) printf("[LOG] " fmt "\n", ##__VA_ARGS__)
LOG2("Error"); /* [LOG] Error */
字符串化与连接组合
#define MAKE_FUNC(name) \
void func_##name(void) { \
printf("Function: %s\n", #name); \
}
MAKE_FUNC(hello) /* 生成 func_hello 函数 */
func_hello(); /* 输出 Function: hello */
编译时断言
#define STATIC_ASSERT(expr) \
typedef char _static_assert_##__LINE__[(expr) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4); /* 编译时检查 */
/* STATIC_ASSERT(sizeof(int) == 8); */ /* 编译错误 */
C11 标准 _Static_assert:
_Static_assert(sizeof(int) == 4, "int must be 4 bytes");
类型泛化(有限)
#define MAX(type) \
type max_##type(type a, type b) { \
return (a) > (b) ? (a) : (b); \
}
MAX(int) /* 生成 max_int */
MAX(double) /* 生成 max_double */
int m = max_int(3, 5);
X-Macro 模式
#define COLORS \
X(RED, 0xFF0000) \
X(GREEN, 0x00FF00) \
X(BLUE, 0x0000FF)
/* 生成枚举 */
#define X(name, value) COLOR_##name = value,
enum Color { COLORS };
#undef X
/* 生成字符串数组 */
#define X(name, value) #name,
const char *color_names[] = { COLORS };
#undef X
常见错误
过度使用宏:
/* 难以调试、难以维护 */
#define BEGIN {
#define END }
#define THEN
#define ELSE else
if (x > 0) THEN BEGIN
printf("positive");
END ELSE BEGIN
printf("non-positive");
END
最佳实践
- 宏技巧用于代码生成,不替代正常代码
- X-Macro 适合重复模式的数据定义
- 编译时断言检查编译期条件
- 复杂宏加详细注释
- 优先用 C 语言特性替代宏技巧