当你从C标准库或C ++ STL中包含一个头文件(.h,.hpp,.hh,.hxx扩展名)时(或者甚至包括像windows.h
这样的Microsoft的大文件),并使用只有一定数量的函数,整个文件是否为二进制文件并被复制到可执行文件中,或者只是正在使用的特定相关函数变成了二进制文件?
如果正在复制整个文件(这就是我认为实际发生的事情,因为windows.h
具有宏定义以减少冗余;例如WIN32_LEAN_AND_MEAN
- 为什么会这样发生?为什么#include
预处理程序命令只复制已使用的函数(以及这些函数在后台使用的其他函数)?它不是更具成本效益吗?
如果只复制相关功能 - 为什么我们首先要做头部包含?为什么我们不需要在需要时使用和编译大量函数,例如PHP等解释语言(以及Python中的某些情况)。如果只是因为“C和C ++已经老了并且已经标准化”,为什么不在他们的新版本中做呢?或者至少现代编译器允许它(我们已经看到编译器弯曲老化语言以支持现代开发人员的情况)?
答案 0 :(得分:3)
头文件只告诉编译器外部函数和变量是什么类型,定义宏,类型等。没有任何东西被复制。在链接器阶段,将链接源文件中引用的任何函数和变量(所谓的外部符号)。
如果在程序中包含stdio.h并使用printf,编译器会将printf作为“未解析”符号添加到目标文件中,然后链接器将尝试在您明确的目标文件中找到名为printf的函数链接,或在配置为搜索的库中。
如前所述,#include文件和将该文件的内容复制到源文件之间没有真正的区别。如果包含的文件包含函数或数据定义(不仅仅是声明),那么这些DO将成为目标文件的一部分。
答案 1 :(得分:0)
将编译整个标题(除了受#if
,#ifdef
等保护的部分,以防止它。)
由于通常在C中完成,所以标头仅包含声明而不是定义,但宏除外。因此,编译头文件主要是将名称放入编译器的符号表中,而不产生任何代码。
在C ++中,标题通常包含实际定义,尤其是在使用模板时。在这种情况下,标题可以包含许多内联函数定义以及类定义和各种声明。
这并不意味着整个内容最终会在最终的可执行文件中结束。现代链接器可以很好地合并同一对象/函数的多个定义,并消除未使用的部分。
像<{1}}这样的宏是为了改善编译时间而发明的。它们通常对最终可执行文件的大小影响很小或没有影响。答案 2 :(得分:0)
编译器不直接读取头文件,而是由预处理器读取头文件,基本上将其直接复制到#include
指令的位置。
由于大多数头文件不包含任何实际代码,只包含声明和宏,因此实际上并没有将这些头文件放入可执行文件中。预处理器解析所有宏和递归#include
指令。剩下的编译器是声明,类型别名(typedef
声明)以及更多声明。声明实际上并不生成任何代码,它们仅在解析和生成实际代码时由编译器用于其内部状态。
您可能想了解the C preprocessor。
答案 3 :(得分:0)
根据我的经验,头文件几乎与文件大小无关,因为几乎所有操作系统都内置了c或c ++,因此没有必要复制二进制文件。
标题对文件大小有影响的唯一情况是它是您创建的文件大小。 WIN32_LEAN_AND_MEAN用于排除几乎从不在头文件中使用的服务。
如果您想了解更多信息,我也发现了other Stack Overflow article.
答案 4 :(得分:0)
此链接是关于make文件编写的: http://www.cs.bu.edu/teaching/cpp/writing-makefiles/ 这个链接描述了h。文件使用: Why have header files and .cpp files in C++?