c语言的头文件是以".h"后缀命名的文件,里面包含了宏定义、变量定义和函数声明等等。
头文件相当于多个.c文件直接交流的桥梁,使得不同的编译单元可以相互通信。
我们在编写c程序的时候,有时需要把一个程序拆分成多个.c文件,不同文件之间的函数如何调用成了问题,编译器如何知道我们正确地调用函数?函数在哪里?
一系列的问题促使了头文件的产生。
有人会问,像Java,Python,C#这些语言都没有头文件,不都活得好好的吗?C语言的头文件意义何在?
c语言是一门古老的语言,在几十年前,当我们的程序有多个源文件的时候,编译器如何在众多编译单元里面找出所有函数?这在当时,计算机无论是存储空间还是运算能力都无法达到这个要求。所以我们需要手动把一些函数的声 明,宏定义等等需要在编译时用到的东西放到一个文件里面,这个文件就是头文件(当然可以有多个)。
有了头文件,编译器就可以在编译的过程中少花一点时间和空间,这与现在编译器应该替我们做更多的事这一观念相违背,但是在当时限于技术和条件,程序员们不得不这么做。写程序就是这样,程序员和编译器总有一个累死。
当然,头文件的作用不仅限于函数声明,在编译阶段头文件的具体作用后文会讨论。
c语言属于一门造轮子的语言,各种场景都能用。放在现如今也有一些对内存限制较严格的开发场景:嵌入式,内核等等。说白了,就是不给硬件太大压力。
编译器在编译文件的时候,需要头文件提供一些信息,这点的作用后文会提及。
使用头文件有利于模块化程序设计,使程序利于维护和拓展
(下面两点引自知呼:)
头文件能加强类型安全检查。若某个接口的实现或使用方式与头文件中的声明不一致,编译器就会指出错误。这一简单的规则能大大减轻程序员调试、改错的负担。
通过头文件调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制库即可。用户只需按照头文件中的接口声明来调用库功能,而不必关心接口如何实现。编译器会从库中提取相应的代码。
一般来说,头文件里面会包含函数声明,宏定义,变量定义,条件预处理。头文件里面还可以包含其它的头文件。基本上就是这些,没有什么特殊的,和我们平时在编写.c文件的时候一模一样。
答案是尽量不要!
假如我们有两个文件同时包含了这个头文件并一起编译,就会有error产生。比如,你有一个c文件叫main.c,一个c文件叫test.c,两个文件都包含头文件header.h,里面实现了某个内容.编译时我们一起编译这两个文件,这就相当于 在这两个.c文件里面同时插入了一模一样的header.h文件的内容,属于重复定义。关于这点可以看一下c语言的命名管理机制。
//max.h
int max(int , int);
在max.h文件里面,我们声明了一个函数max,该头文件对应的.c文件为max.c,max.c文件代码如下:
int max(int x, int y)
{
return x > y ? x : y;
}
在main.c里面,我们通过包含max.h,然后调用max函数:
#include "max.h"
int main(void)
{
max(10);
return 0;
}
这就是一个简单的头文件使用的例子。当然,严格一点,我们需要在max.h文件里面使用预处理判断语句,判断max.h文件是否被定义过了。这点可以参考c语言的预处理指令。
关于在头文件中定义宏,声明变量等等操作大家可以自己尝试,下面主要讨论头文件的组织原则:
头文件不要太大。如果头文件太大,会严重降低编译速度!!所以在头文件中尽量不要包含其它头文件,应在所使用的头文件的.c文件中包含。
源文件中实现变量、函数的定义,并指定链接范围。头文件中书写外部需要使用的全局变量、函数声明及数据类型和宏的定义。
对于大量的宏定义,函数声明等,应该使用多个头文件分离,或者按照关系紧密程度组织头文件。
头文件名应尽量与实现功能的源文件相同,即module.c和module.h。但源文件不一定要包含其同名的头文件。
头文件适合放置接口的声明,不适合放置实现。 变量的声明尽量不要放在头文件,尽量不要使用全局变量作为接口。变量是模块的内部实现细节,不应通过头文件声明的方式直接暴露给外部,应通过函数接口的方式对外暴露。
头文件应自包含(自包含就是任意一个头文件均可独立编译)
关于c语言头文件,暂时讨论至此,头文件的其它用法及更详细的代码展示会放到“浅谈c语言头文件(2)”中进行讨论
本文部分内容来源与网络,侵权必删;文章如有批漏或错误,欢迎留言提醒
原文:https://www.cnblogs.com/laoxuezhou-blogs/p/node-1.html