Skip to content

Latest commit

 

History

History
80 lines (58 loc) · 3.31 KB

14-头文件.md

File metadata and controls

80 lines (58 loc) · 3.31 KB

头文件

头文件是扩展名为.h的文件,包含了C函数声明和宏定义,被多个源文件中引用共享。头文件中一般放的是同名.c文件中定义的变量、数组、函数的声明,需要让.c外部使用的声明。

有两种类型的头文件:

  • 程序员编写的头文件
  • 编译器自带的头文件。

使用#include来引用头文件,include头文件只是把头文件的内容复制到引用它的地方。并没有什么复杂的操作

头文件作用:

  1. 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明;
  2. 使函数的作用域从函数声明的位置开始,而不是函数定义的位置(实践总结)
  3. 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h)。

使用头文件:

  • 头文件中可以有什么:明示常量、结构体、类型定义、函数或变量申明、宏函数。
  • 头文件不应该有:变量定义、 函数定义。

1 只引用一次头文件

如果一个头文件被引用两次,编译器会处理两次头文件的内容,这将产生错误。为了防止这种情况,标准的做法是把文件的整个内容放在条件编译语句中,如下:

#ifndef HEADER_FILE//如果没有定义HEADER_FILE,就往下走,一直到#endif,否则直接跳到#endif
#define HEADER_FILE

头文件的内容

#endif

这样头文件的内容就会被定义一次了


2 有条件引用

有时需要从多个不同的头文件中选择一个引用到程序中。例如,需要指定在不同的操作系统上使用的配置参数。

一般的做法是:

#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 定义。


3 如何组织好头文件

  1. 每个由.c和.h文件组成的模块都应符合清晰的功能
  2. 总是在头文件中使用『包含文件防护』,即只引用一次头文件
  3. 把使用本模块需要的声明都放在头文件中,这个文件也常被用来访问此模块。
  4. 头文件只包含声明,并且他要在其.c文件中被导入
  5. 将外部全局变量的声明使用extern修饰后放在头文件里,并且把声明定义放在.c文件中
  6. 把模块内部的声明移出头文件,不暴露不需要暴露的
  7. 每个头文件的都应仅仅导入此头文件所必须的一些头文件,来让这个头文件能够被正确地编译
  8. 如果仅仅要使用一个未完全声明的结构体,那么就不用导入他对应的头文件了
  9. 一个头文件应当能被他自身所成功编译
  10. A.c文件应该最先导入A.h文件,之后再导入其他所需的头文件
  11. 永远不要因为任何原因导入一个.c文件

具体参考 如何组织好 C 的头文件