6.3 预处理器与头文件

本篇学习 `#include`、宏、预定义宏、条件编译和头文件保护,并能组织简单的多文件 C 项目。

预处理器与头文件

概念说明

预处理器会在正式编译前先处理源码中的预处理指令。 最常见的预处理任务包括头文件包含、宏替换和条件编译。

头文件的作用是共享声明。 一个更像样的 C 项目通常会把函数声明、结构体声明和宏定义放进 .h 文件,再把具体实现放在 .c 文件中。

预处理并不等于“只是 include 一下”。 它还会影响代码组织、调试信息输出、平台适配和编译开关控制,所以是 C 工程基础里非常关键的一部分。

语法/规则

  1. #include <stdio.h> 常用于包含标准库头文件,#include "my.h" 常用于包含项目自己的头文件。
  2. #define 会进行文本替换,编写宏时通常要给参数和整体表达式补括号。
  3. 函数式宏适合非常短小的表达式封装,但带副作用的参数要格外谨慎。
  4. 常见预定义宏有 __FILE____LINE____DATE____TIME__
  5. 条件编译常见写法有 #if#ifdef#ifndef#elif#else#endif
  6. defined 可用于配合 #if 检查某个宏是否已经定义。
  7. 头文件应加保护宏,避免被重复包含;必要时也可以用 #error 在配置不满足时直接阻止编译。

示例

1
2
3
4
5
6
7
8
9
/* math_tools.h */
#ifndef MATH_TOOLS_H
#define MATH_TOOLS_H

#define SQUARE(x) ((x) * (x))

int add(int a, int b);

#endif
1
2
3
4
5
6
/* math_tools.c */
#include "math_tools.h"

int add(int a, int b) {
    return a + b;
}
1
2
3
4
5
6
7
8
9
/* main.c */
#include <stdio.h>
#include "math_tools.h"

int main(void) {
    printf("sum = %d\n", add(3, 4));
    printf("square = %d\n", SQUARE(3));
    return 0;
}

输出结果:

1
2
sum = 7
square = 9

常见错误

  1. 头文件没有保护宏,被重复包含后出现重复定义问题。
  2. 宏没有加括号,例如 #define SQUARE(x) x * x,在复杂表达式里结果会出错。
  3. 把大量实现代码直接塞进头文件,导致多文件编译和链接变得混乱。
  4. 用条件编译控制平台差异时没有把分支写完整,结果某些环境下直接编译不过。
  5. 在宏参数里传入带副作用的表达式,却没有意识到宏展开可能导致重复求值。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字