C语言中的#define是预处理阶段执行的指令,主要用于定义宏,能够在编译前对代码中的特定标识符进行替换,是C语言编程中非常基础且常用的功能。

#define的基本语法
#define的核心作用就是文本替换,基本语法格式为#define 宏名 替换文本,预处理阶段会把代码中所有出现宏名的位置替换成对应的替换文本。
无参宏定义
无参宏是最简单的宏定义形式,没有参数,直接进行文本替换,示例如下:
#include <stdio.h>
// 定义无参宏,用PI替换3.14159
#define PI 3.14159
int main() {
float radius = 5.0;
// 预处理后这里会变成 float area = 3.14159 * 5.0 * 5.0;
float area = PI * radius * radius;
printf("圆的面积是:%fn", area);
return 0;
}
带参宏定义
带参宏可以接收参数,类似函数的形式,但是本质是文本替换,不是函数调用,语法格式为#define 宏名(参数列表) 替换文本,示例如下:
#include <stdio.h>
// 定义带参宏,计算两个数的乘积
#define MULTIPLY(a, b) a * b
int main() {
int x = 3, y = 4;
// 预处理后变成 int result = 3 * 4;
int result = MULTIPLY(x, y);
printf("乘积是:%dn", result);
return 0;
}
#define的使用注意事项
- 宏定义末尾不需要加分号,如果加了分号,分号也会被当成替换文本的一部分,可能导致语法错误。
- 带参宏的参数最好用括号包裹,替换文本整体也最好用括号包裹,避免运算符优先级问题导致结果错误。比如上面的MULTIPLY宏如果写成
#define MULTIPLY(a, b) a * b,当调用MULTIPLY(1+2, 3)时,替换后会变成1+2 * 3,结果是7而不是预期的9,正确的写法应该是#define MULTIPLY(a, b) ((a) * (b))。 - 宏的作用范围是从定义位置开始到文件结束,如果需要提前终止宏的作用,可以使用
#undef 宏名指令。
宏和函数的区别
很多带参宏的功能和函数类似,但是两者有本质区别,具体对比如下:
| 对比项 | 宏 | 函数 |
|---|---|---|
| 执行阶段 | 预处理阶段替换 | 运行时调用 |
| 参数类型 | 无类型检查,任意合法文本都可以替换 | 有严格的参数类型检查 |
| 开销 | 无调用开销,但是多次使用会增大代码体积 | 有调用开销,但是代码体积不会额外增大 |
| 是否可调试 | 预处理后宏就不存在了,无法调试 | 可以正常调试 |
常见使用场景
#define除了定义常量和简单计算宏之外,还可以用来定义条件编译的开关,比如:
#include <stdio.h>
// 定义调试开关宏
#define DEBUG
int main() {
#ifdef DEBUG
printf("调试信息:程序开始运行n");
#endif
printf("正常业务逻辑n");
return 0;
}
当定义了DEBUG宏时,预处理阶段会保留调试信息的打印代码,如果注释掉#define DEBUG,那么调试打印的代码就会被删除,方便开发阶段和发布阶段的代码切换。