我为什么要包含头文件?#include实际上如何运作?

Zag*_*rax 4 c header-files

起初,我在.h文件中编写我的函数,然后将其包含在内#include "myheader.h".然后,有人说我最好只添加这些文件的函数原型并将实际代码放在一个单独的.c文件中.现在,我能够编译更多.c文件以仅生成可执行文件,但此时我无法理解为什么我应该添加头文件,如果代码在另一个文件中.

此外,我看了系统中的标准C库(比如stdlib.h),在我看来只存储结构定义,常量和类似...我不太喜欢C(说实话,stdlib.h)对我来说几乎是中国人,当然中国人没有冒犯:)),但我没有发现任何一行"操作"代码.但是,我总是只包含它而不添加任何其他东西,我编译我的文件,好像'代码'实际上在那里.

有人可以解释一下这些东西是如何运作的吗?或者,至少,请指点一个好导游?我也搜索了Google和SO,但没有找到任何可以解释清楚的内容.

MrT*_*rTJ 16

编译C代码时,编译器必须实际知道存在具有已定义名称,参数列表,返回类型和可选修饰符的特定函数.所有这些都被称为函数签名,并且在头文件中声明了特定函数的存在.有了这些信息,当编译器找到对这个函数的调用时,它将知道要查找哪种类型的参数,可以控制它们是否具有相应的类型,并将它们准备到一个结构,该结构将在代码实际执行之前被推送到堆栈跳转到你的函数实现.但是编译器不必知道函数的实际实现,它简单地将对象文件中的"占位符"放到所有函数调用中.(注意:每个c文件只编译一个目标文件).#includesimple获取头文件并将该#include行替换为该文件的内容.

编译之后,构建脚本将所有目标文件传递给链接器.链接器将解析所有函数"占位符",找到函数实现的物理位置,让它们成为您的目标文件,框架库或dll.它简单地将信息放在可以找到所有函数调用的函数实现的位置,这样您的程序就会知道在它到达函数调用时继续执行的位置.

说完这一切之后,应该清楚为什么你不能把函数定义放在头文件中.如果稍后您#include将此标头放入多个c文件中,则它们都会将函数实现编译为两个单独的目标文件.编译器可以很好地工作,但是当链接器想要将所有内容链接在一起时,它会找到该函数的两个实现并且会给你一个错误.

stdlib.h和朋友一样工作.它们中声明的函数的实现可以在框架库中找到,即使您没有意识到,编译器也会"自动"链接到您的代码.