宏定义
#define 定义宏,预处理器在编译前将宏名替换为宏体。宏可以定义常量、简化代码、提高可读性。但宏是纯文本替换,没有类型检查,使用不当会导致难以发现的错误。
常量宏
#define PI 3.14159265359
#define MAX_SIZE 100
#define BUFFER_LEN 1024
/* 使用 */
double circumference = 2 * PI * radius;
int arr[MAX_SIZE];
与 const 对比
#define MAX 100 /* 宏:无类型,预处理器替换 */
const int max = 100; /* 常量:有类型,编译器处理 */
/* 宏的问题 */
#define SIZE sizeof(int)
int arr[SIZE]; /* 合法 */
const int size = sizeof(int);
int arr2[size]; /* C99 VLA,但某些编译器可能不支持 */
多行宏
#define SWAP(a, b) do { \
typeof(a) temp = (a); \
(a) = (b); \
(b) = temp; \
} while(0)
do { ... } while(0) 技巧让宏在任何上下文中都像一条语句。
取消定义
#define DEBUG 1
/* ... */
#undef DEBUG /* 取消定义 */
#ifdef DEBUG
/* 不会执行 */
#endif
字符串化
#define STRINGIFY(x) #x
printf("%s\n", STRINGIFY(hello)); /* 输出 "hello" */
printf("%s\n", STRINGIFY(1 + 2)); /* 输出 "1 + 2" */
连接
#define CONCAT(a, b) a##b
int xy = 10;
printf("%d\n", CONCAT(x, y)); /* 输出 xy 的值:10 */
常见错误
缺少括号:
#define SQUARE(x) x * x
int result = SQUARE(3 + 4); /* 3 + 4 * 3 + 4 = 19,不是 49 */
/* 正确 */
#define SQUARE(x) ((x) * (x))
副作用:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int x = 5, y = 3;
int m = MAX(x++, y++); /* x 或 y 可能自增两次 */
最佳实践
- 宏体用括号包围
- 参数也用括号包围
- 优先用
const、enum、inline替代宏 - 多行宏用
do { ... } while(0) - 宏名全大写,与变量区分