在C语言里,宏定义是预处理指令的一种,通过#define在编译前对代码做文本替换。它常用来定义常量、简化重复代码或者做条件编译,是C开发中非常基础也很容易踩坑的特性。

宏定义的基本用法
最简单的宏定义是定义常量,例如下面这样:
#include <stdio.h>
#define PI 3.14159
#define MAX_SIZE 100
int main() {
printf("PI = %fn", PI);
int arr[MAX_SIZE];
return 0;
}
带参数的宏类似于函数,但本质是替换:
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
int main() {
int a = 5;
printf("square = %dn", SQUARE(a));
return 0;
}
宏定义的常见用途
- 定义全局常量,避免魔法数字
- 定义简单运算,减少函数调用开销
- 配合
#ifdef做跨平台或调试开关
使用宏定义的注意事项
1. 括号问题
宏只是文本替换,参数和整体都要加括号,否则运算符优先级会出问题。比如写#define MUL(a,b) a*b,调用MUL(1+2,3)会展开成1+2*3,结果错误。正确写法是#define MUL(a,b) ((a)*(b))。
2. 参数副作用
带参宏如果传入带副作用的表达式,会被展开多次。例如:
#include <stdio.h>
#define DOUBLE(x) ((x) + (x))
int main() {
int i = 1;
int r = DOUBLE(i++); // 展开为 ((i++) + (i++))
printf("r = %d, i = %dn", r, i);
return 0;
}
上面代码中i++执行了两次,结果不符合直觉,应改用函数。
3. 重复定义与头文件保护
在头文件里定义宏时,要用#ifndef防止重复包含:
#ifndef MY_HEADER_H #define MY_HEADER_H #define BUFFER_LEN 256 #endif
4. 宏名冲突
宏没有作用域概念,定义后直到#undef或文件结束都有效。建议宏名全部大写,并在不需要时及时#undef。
宏与函数的选择
| 对比项 | 宏 | 函数 |
|---|---|---|
| 类型检查 | 无 | 有 |
| 调试 | 不易调试 | 可单步 |
| 开销 | 无调用开销 | 有栈开销 |
简单且频繁调用的短逻辑可用宏,复杂逻辑和需要类型安全的场景应使用函数。掌握这些要点,就能更安全地把宏用在C语言项目中。