头文件重复包含

← C语言知识地图 | ← 主页


问题:如何发生的

// a.h
typedef struct { int x; } A;

// b.h
#include "a.h"

// main.c
#include "a.h"
#include "b.h"   // a.h 被展开第二次 → A 重复定义 → 编译报错

预处理阶段 #include 就是文本复制粘贴。同一个 .h 被多链条引入时,里面的定义出现在翻译单元中 ≥2 次,编译器报重复定义

⚠️ 函数/变量声明重复没事,但 typedefstruct 定义、宏等重复就会炸。


解决 1:#ifndef 守卫(传统/跨平台)

// a.h
#ifndef A_H
#define A_H
 
typedef struct { int x; } A;
 
#endif

第一次包含时:

  1. #ifndef A_H:预处理器检查——“A_H 这个标志被定义过吗?” → 没有
  2. #define A_H:预处理器说”好,那我现在定义它!”
  3. typedef struct { int x; } A;:头文件里的真正内容被正常展开,送到编译器去编译。
  4. #endif:条件结束。

第二次包含时:

  1. #ifndef A_H:预处理器再次检查——“A_H 这个标志被定义过吗?” → 刚才已经定义过了!
  2. 跳过内容:条件不成立,预处理器直接删掉/跳过从 #ifndef#endif 之间的所有代码。

结果:第二次包含在编译期变成”一片空白”,代码自然就不会被定义两次了。

命名约定文件名_H(大写),或用 项目_模块_文件名_H 避免同库冲突。


解决 2:#pragma once(简洁/非标准但主流编译器都支持)

// a.h
#pragma once
 
typedef struct { int x; } A;

一行搞定:编译器认得这个文件,下次再 #include 直接跳过。