头文件是扩展名为.h
的文件,包含了C函数声明和宏定义,被多个源文件中引用共享。头文件中一般放的是同名.c
文件中定义的变量、数组、函数的声明,需要让.c
外部使用的声明。
有两种类型的头文件:
- 程序员编写的头文件
- 编译器自带的头文件。
使用#include
来引用头文件,include头文件只是把头文件的内容复制到引用它的地方。并没有什么复杂的操作
头文件作用:
- 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明;
- 使函数的作用域从函数声明的位置开始,而不是函数定义的位置(实践总结)
- 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h)。
使用头文件:
- 头文件中可以有什么:明示常量、结构体、类型定义、函数或变量申明、宏函数。
- 头文件不应该有:变量定义、 函数定义。
如果一个头文件被引用两次,编译器会处理两次头文件的内容,这将产生错误。为了防止这种情况,标准的做法是把文件的整个内容放在条件编译语句中,如下:
#ifndef HEADER_FILE//如果没有定义HEADER_FILE,就往下走,一直到#endif,否则直接跳到#endif
#define HEADER_FILE
头文件的内容
#endif
这样头文件的内容就会被定义一次了
有时需要从多个不同的头文件中选择一个引用到程序中。例如,需要指定在不同的操作系统上使用的配置参数。
一般的做法是:
#if SYSTEM_1//如果是系统1,就引用system_1.h
# include "system_1.h"
#elif SYSTEM_2////否则是系统2,就引用system_2.h
# include "system_2.h"
#elif SYSTEM_3
...
#endif
但是如果头文件比较多的时候,这么做就很繁琐,预处理器使用宏来定义头文件的名称。这就是所谓的有条件引用。 它不是用头文件的名称作为 #include 的直接参数,只需要使用宏名称代替即可:
#define SYSTEM_H "system_1.h"
...
#include SYSTEM_H
SYSTEM_H 会扩展,预处理器会查找 system_1.h,就像 #include 最初编写的那样。SYSTEM_H 可通过 -D 选项被Makefile 定义。
- 每个由.c和.h文件组成的模块都应符合清晰的功能
- 总是在头文件中使用『包含文件防护』,即只引用一次头文件
- 把使用本模块需要的声明都放在头文件中,这个文件也常被用来访问此模块。
- 头文件只包含声明,并且他要在其.c文件中被导入
- 将外部全局变量的声明使用extern修饰后放在头文件里,并且把声明定义放在.c文件中
- 把模块内部的声明移出头文件,不暴露不需要暴露的
- 每个头文件的都应仅仅导入此头文件所必须的一些头文件,来让这个头文件能够被正确地编译
- 如果仅仅要使用一个未完全声明的结构体,那么就不用导入他对应的头文件了
- 一个头文件应当能被他自身所成功编译
- A.c文件应该最先导入A.h文件,之后再导入其他所需的头文件
- 永远不要因为任何原因导入一个.c文件
具体参考 如何组织好 C 的头文件