问题
在进行C语言文件移植时,遇到 “通常是每个.c文件对应一个.h文件”,之前了解过.h文件是头文件,用来引用其他文件的,
但在codeblocks C语言项目中找不到相应的.h文件:
所以,.c和.h文件到底什么关系,又怎么对应?
答案
.h文件的由来
“在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件。但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件。
于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句。这样即使某个声明发生了变更,也再不需要到处寻找与修改了。因为这个新文件,经常被放在.c(.cpp)文件的头部,所以就给它起名叫做“头文件”,扩展名是.h。
在我们语言的初学阶段,往往我们的程序只有一个.c的文件或这很少的几个,这时我们就很少遇到头文件组织这个头疼的问题,随着我们程序的增加,代码 量到了几千行甚至几万行,文件数也越来越多。这时这些文件的组织就成了一个问题,其实说白了这些文件的组织问题从理论上来说是软件工程中的模块设计等等的问题。”
由上可以看出,.h文件最初就是用来给变量和函数提供一些全局性的声明,这些声明被其他.c文件共享,方便变量和声明的修改,使得大型代码逻辑更清晰更易于维护。因此.h文件中一般是声明,很少有代码的具体实现。
那么为什么在.h文件中实现函数也不会出错呢?
【在.h文件中实现函数与在.c文件中实现函数有什么区别和联系呢?】
要解决上述问题,首先必须弄清编译器的工作原理。编译器的最终目的是将程序员编写的源代码转换成机器能够识别运行的二进制机器码。
大体上分,可以分为4个步骤:
1.头文件的预编译,预处理
编译器在编译源代码时,会先编译头文件,保证每个头文件只被编译一次。
在预处理阶段,编译器将c文件中引用的头文件中的内容全部写到c文件中。
2.词法和语法分析(查错)
3.编译(汇编代码,.obj文件)
转化为汇编码,这种文件称为目标文件。后缀为.obj。
4.链接(二进制机器码,.exe文件)
将汇编代码转换为机器码,生成可执行文件。
因此,在编译过程中,.h文件中的所有内容会被写到包含它的.c文件中,而所有的.c文件以一个共同的main函数作为可执行程序的入口。
在.h文件中编写函数实现并不会出错,相当于所有.h的内容最后都被写到了main.c文件中。但是为了逻辑性、易于维护性以及一些其他目的,一般在.h文件中写函数的声明,在.c文件中编写函数的实现。
总的来说:
C程序的入口是main()函数,当我们遇到一个比较大的程序,需要被每个功能模块区分开始,就需要使用不同的.c和.h文件。这样方便自己管理和使用c程序,.h是头文件,一般存放函数的声明、数组、和定义的变量,.c是源文件,是实现函数程序的功能。
如何使用.c和.h呢?
首先需要建立一个xx.h文件,这里面是函数的声明和一些变量的定义,其次建立一个同名的xx.c文件,这里面是实现某个函数的功能例如(xiangcheng(int a,intb)),然后新建一个xx.c文件这里面是实现xiangcheng(int a,int b)的函数,当需要调用这个xiangcheng(int a,int b)的函数时只需要在函数的头部加上xx.h头文件即可,这样就完成了不同文件函数之间的调用。