预处理器基础
预处理器是 C 编译的第一个阶段,在编译器看到代码之前处理源代码。预处理器处理以 # 开头的指令,包括文件包含、宏定义、条件编译等。预处理器是文本替换工具,不进行类型检查,理解这一点对避免宏相关错误至关重要。
预处理指令
#include <stdio.h> /* 包含系统头文件 */
#include "myheader.h" /* 包含用户头文件 */
#define PI 3.14159 /* 定义常量宏 */
#define MAX(a, b) ((a)>(b)?(a):(b)) /* 定义函数式宏 */
#ifdef DEBUG /* 条件编译 */
printf("Debug info\n");
#endif
#pragma once /* 编译器特定指令 */
预处理阶段
源代码 → 预处理器 → 编译器 → 汇编器 → 链接器 → 可执行文件
↑
文本替换、文件包含、条件编译
查看预处理结果
# GCC
gcc -E program.c > program.i /* 只预处理 */
gcc -E program.c | grep -v "^#" /* 去掉行号信息 */
常见指令
| 指令 | 功能 |
|---|---|
#include | 包含头文件 |
#define | 定义宏 |
#undef | 取消宏定义 |
#ifdef | 如果定义了宏 |
#ifndef | 如果没定义宏 |
#if | 如果表达式为真 |
#elif | 否则如果 |
#else | 否则 |
#endif | 结束条件 |
#error | 产生错误 |
#pragma | 编译器特定指令 |
常见错误
忘记 #endif:
#ifdef DEBUG
printf("Debug\n");
/* 忘记 #endif → 编译错误 */
在宏定义中使用分号:
#define MAX 100; /* 错误:MAX 替换为 100; */
int arr[MAX]; /* 变成 int arr[100;]; */
最佳实践
- 宏名全大写(约定)
- 用
const和inline替代简单宏 - 条件编译注意
#endif配对 - 理解预处理器是纯文本替换
- 用
#error检查配置一致性