参考博客:html
c语言中.h文件和.c文件的解析 程序员
编译器的工做过程函数
最近在作一个稍微有些复杂的项目。涉及到的函数、结构体、变量等比较多。一般,我编写c/c++项目的方式是,有一个main.c文件,该文件的main函数做为接口,调用其余函数。全部其余函数按功能,分别放在不一样的.h文件中,这样的方式在编译和运行上确定是没有什么问题的。编码
随着项目编写的深刻,结构、逻辑以及变量的日趋复杂,总感受上述方式的实现仍然不够清晰而且会致使一些冗余。突然记起,在课堂上,老师提到过,.h文件通常用来存放函数声明和变量名,那么为何我在.h文件中实现函数不会有问题呢?其余.c文件和main.c文件又有什么关系呢?这些,都使我不得不从新思考.h文件和.c文件的做用和关系。spa
要理清.h文件的做用,咱们不妨看看.h文件的由来:.net
“在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了不少的.c(.cpp)文件,渐渐地,人们发如今不少.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每一个.c(.cpp)文件。但更为恐怖的是,当其中一个声明有变动时,就须要检查全部的.c(.cpp)文件。
因而人们将重复的部分提取出来,放在一个新文件里,而后在须要的.c(.cpp)文件中敲入#include XXXX这样的语句。这样即便某个声明发生了变动,也再不须要处处寻找与修改了。由于这个新文件,常常被放在.c(.cpp)文件的头部,因此就给它起名叫作“头文件”,扩展名是.h。
在咱们语言的初学阶段,每每咱们的程序只有一个.c的文件或这不多的几个,这时咱们就不多遇到头文件组织这个头疼的问题,随着咱们程序的增长,代码 量到了几千行甚至几万行,文件数也愈来愈多。这时这些文件的组织就成了一个问题,其实说白了这些文件的组织问题从理论上来讲是软件工程中的模块设计等等的问题。”(引自c语言项目中.h文件和.c文件的关系)设计
由上能够看出,.h文件最初就是用来给变量和函数提供一些全局性的声明,这些声明被其余.c文件共享,方便变量和声明的修改,使得大型代码逻辑更清晰更易于维护。所以.h文件中通常是声明,不多有代码的具体实现。htm
那么为何在.h文件中实现函数也不会出错呢?在.h文件中实现函数与在.c文件中实现函数有什么区别和联系呢?普通的.C文件和包含main函数的c文件有什么区别和联系呢?blog
要解决上述问题,首先必须弄清编译器的工做原理。编译器的最终目的是将程序员编写的源代码转换成机器可以识别运行的二进制机器码。大致上分,能够分为4个步骤:
1.头文件的预编译,预处理
编译器在编译源代码时,会先编译头文件,保证每一个头文件只被编译一次。
在预处理阶段,编译器将c文件中引用的头文件中的内容所有写到c文件中。
2.词法和语法分析(查错)
3.编译(汇编代码,.obj文件)
转化为汇编码,这种文件称为目标文件。后缀为.obj。
4.连接(二进制机器码,.exe文件)
将汇编代码转换为机器码,生成可执行文件。
更详细具体的流程可参考编译器的工做过程
在编译过程当中,.h文件中的全部内容会被写到包含它的.c文件中,而全部的.c文件以一个共同的main函数做为可执行程序的入口。
所以,在.h文件中编写函数实现并不会出错,至关于全部.h的内容最后都被写到了main.c文件中。
可是为了逻辑性、易于维护性以及一些其余目的(可参考c语言中.h文件和.c文件的解析 ),通常在.h文件中写函数的声明,在.c文件中编写函数的实现。