C语言专题:15.宏定义与控制指令(#define、#ifndef、#undef、#defined)
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 100int 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) // 空宏,不执行
#endifLOG(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
函数中; -
写宏时一定要注意括号和命名,避免产生预处理陷阱。