C语言的预处理阶段为我们提供了灵活而强大的宏机制,其中 #define 用于定义宏常量与宏函数,配合 #ifndef、#undef 和 defined 可以实现条件编译、头文件保护、功能开关、调试控制等。
一、#define:定义宏
1.1 宏常量
#define PI 3.14159
#define MAX_LEN 100
所有后续代码中出现
PI都会被预处理器替换成3.14159;宏没有类型限制,完全是文本替换。
1.2 宏函数(带参数)
#define SQUARE(x) ((x) * (x))
示例:
printf("%d\n", SQUARE(5)); // 输出 25
注意:
必须使用括号保护参数和整个表达式;
宏没有类型检查,不推荐写过于复杂的表达式。
1.3 多行宏定义
#define LOG(msg) \
printf("[LOG] %s\n", msg); \
fflush(stdout);
使用 \ 表示换行宏,便于格式化长逻辑块。
二、#ifndef:判断未定义宏
2.1 基本语法
#ifndef 宏名
// 如果未定义这个宏,执行这部分
#endif
常用于头文件保护:
// file: mylib.h
#ifndef MYLIB_H
#define MYLIB_H
// 声明内容...
#endif
目的:防止多次包含头文件造成重定义错误。
2.2 使用场景
| 场景 | 示例 |
|---|---|
| 头文件保护 | #ifndef MY_H ... #endif |
| 防止重复定义 | #ifndef MAX_SIZE #define MAX_SIZE 100 |
| 功能模块开关 | #ifndef DISABLE_SOUND |
三、#undef:取消宏定义
#define DEBUG
#undef DEBUG
取消宏定义后,
#ifdef DEBUG条件将返回 false;可用于临时关闭某些功能或在不同区块重新定义。
四、defined 运算符(用于条件判断)
4.1 基本语法
#if defined(DEBUG)
printf("Debug Mode\n");
#endif
也可用于逻辑判断:
#if defined(DEBUG) && !defined(NLOG)
printf("Debug and Logging\n");
#endif
defined是一个预处理器内置运算符;只能用于
#if/#elif表达式中。
4.2 推荐写法对比
| 写法 | 说明 |
|---|---|
#ifdef A |
宏 A 被定义 |
#if defined(A) |
更通用,适用于复杂表达式 |
#if !defined(A) |
等价于 #ifndef A |
五、宏机制工作原理示意
#define MAX 100
int arr[MAX];
预处理后等价于:
int arr[100];
宏处理发生在编译前的预处理阶段;
宏不会出现在目标文件(.o / .exe)中;
仅是文本层面的替换。
六、实战:条件编译 + 宏定义联合应用
#define WINDOWS
#define ENABLE_LOG
#if defined(WINDOWS)
#define PLATFORM_NAME "Windows"
#else
#define PLATFORM_NAME "Other"
#endif
#ifdef ENABLE_LOG
#define LOG(msg) printf("[LOG] %s\n", msg)
#else
#define LOG(msg) // 空宏,不执行
#endif
LOG(PLATFORM_NAME); // 输出: [LOG] Windows
七、宏指令 vs const vs inline
| 功能 | #define |
const |
inline |
|---|---|---|---|
| 类型检查 | 无 | 有 | 有 |
| 是否占用内存 | 不占 | 占 | 编译器决定 |
| 调试查看 | 不可调试 | 可查看 | 可查看 |
| 替代时机 | 编译前(预处理) | 编译时 | 编译/链接时 |
| 推荐使用场景 | 控制编译结构 | 常量表达式 | 小函数、性能优化 |
八、注意事项与建议
| 问题 | 说明 |
|---|---|
| 宏函数缺括号 | #define SQR(x) x*x,会导致错误计算 |
| 宏名冲突 | 尽量加前缀,如 MYLIB_MAX_SIZE |
| 重定义宏 | 建议先 #undef 后重新定义 |
| 宏调试困难 | 使用 const 替代复杂值更方便调试 |
| 滥用宏 | 建议宏只用于控制编译、常量表达式、调试开关等 |
九、小结一览表
| 指令 | 功能说明 | 示例 |
|---|---|---|
#define |
定义宏常量或宏函数 | #define PI 3.14 |
#undef |
取消已定义的宏 | #undef DEBUG |
#ifndef |
如果宏未定义,则编译对应代码 | #ifndef MYLIB_H |
defined |
条件判断中测试宏是否定义 | #if defined(WIN32) |
十、结语
#define是 C 语言最基础的预处理机制,适用于常量定义与条件控制;搭配
#ifdef/#ifndef/#undef/#defined可以实现灵活的编译开关管理;宏强大但容易滥用,推荐将复杂逻辑迁移到
const或inline函数中;写宏时一定要注意括号和命名,避免产生预处理陷阱。