[英]What exactly happens when a header file is included?
我有两个疑问:
C和C ++是语言,广泛使用称为函数转发的功能 。 这意味着,您可以说,例如:
void f(int i); /* note the semicolon */
这意味着:“我保证,有些人会在源代码中稍后定义,函数f实际上做了什么”。 在这样的转发之后 ,您可以使用此函数,因为它确实存在,并且编译器将要求某人稍后实际定义此函数(如果没有定义,则编译将失败)。 此转发也称为标头,因为它实际上是函数定义的标头:
void f(int i) /* Header */
/* Body */
{
/* ... */
}
头文件是一个文件,主要包含此类转发。 您可以使用头文件来访问其他位置定义的函数(例如,在不同的编译单元或外部库中),然后附加所需的目标文件或库以提供这些头文件的实现。 除了函数转发之外,在头文件中还可以找到正确使用已定义函数所需的结构定义,常量或其他项。
编译器如何将您的转发与.c文件中的实际实现相匹配? 简单地说 - 通过标题 。 它试图找到一个函数定义(实现),它与您之前声明的头完全匹配。
如果#include
头文件是编译器(具体地说,预处理器)将头文件的全部内容复制到位,您放置#include
。 这都是魔术,没有更多的事情发生。
在运行时,头文件根本不重要,因为您的可执行文件只包含可执行代码。 编译器要么加载库中可用的所有函数(可以通过头文件访问),要么(如果打开优化,则很可能)只选择您在代码中实际使用的这些函数。
有趣的是,只有当某人实际使用该功能时,编译器才需要函数定义(实现)。 否则,前转将被忽略。 尝试:
void f(int i);
int main(int argc, char ** argv)
{
/* Do not use f here */
return 0;
}
头文件实际包含什么? 所有的函数定义还是只有原型声明?
头文件包含函数声明,外部变量,宏,结构等。最佳做法是保持函数定义在.c
文件中。
当我包含头文件时会发生什么? 是否将头文件的所有内容附加到我的代码中? 或者是否将头文件的特定(或全部)内容加载到内存中并根据我的代码调用函数?
头文件只不过是在你使用#include
的地方插入它们的内容。 如果您愿意,您可以自己编写所有内容。
包含头文件等于复制头文件的内容,但我们不这样做,因为它会非常容易出错,并且在源文件中复制头文件的内容不是一个好主意,特别是我们有多个源文件,包含我们的程序。
编辑:
有关完整执行程序的内存布局,请访问此链接http://fgiasson.com/articles/memorylayout.txt
头文件应该包含函数(可能是变量)的有用声明和类型( struct
, union
, enum
或typedef
)和宏(类似函数或类似对象的宏)的定义。 这些通常声明某些库的某些部分提供的设施。 例如,标准头文件(例如<stdio.h>
)描述了标准库的部分内容。 现代标题可能包含inline
函数定义,但除此之外,标题既不应定义函数也不应定义变量 - 它应该只声明它们。
另请注意,公共标头通常只应声明对源代码的使用者有用的类型和函数。 它应该只包括其他标题,这些标题提供了使用标题中的工具所必需的声明; 它不应该(通常)包含只有标头描述的工具实现所需的无关头。
头文件的内容(以及它包含的任何头文件)被复制到翻译单元(TU)中。 注意#define
宏和条件处理( #if
等)。 您通常可以找到一种方法来查看给定源文件上的预处理器的输出,以查看C编译器实际看到的内容(但要小心;它可能非常详细)。 例如,选项通常为-E
(POSIX为c99
命令所需)或-P
(较旧的常用选项)。
TU是编译器正确看到的。 它包含文件中的源代码以及您包含的标头中的相关信息。
只是旁注,可能很明显......
ad 2 /如果#include文件,included文件中的#include指令将被包含的文件重新定义。 这就是发生的事情。 这就是预处理器的作用。 通过定义
ad 1 /头文件可以继续任何内容(编译器可以接受的任何内容)。 其他答案描述了用于在c和h文件之间组织代码的常规约定,但这些只是约定。 他们非常善于坚持,如果你不这样做,你可能会因为一个更大的项目而迷失方向。
实际上,如果你为一个非常简单的微控制器写c,你可以完全没有头文件及其包含。
如果您是学生/爱好者/有时间,可能有用的是,分别运行预处理器看看它的中间输出。 有趣的事实:很久以前我曾经使用c预处理器生成coustomized字母。
无论如何,我的观点是: c预处理器的作用是由标准定义的,同时在文件之间交换代码,这是您/您的团队可以在一定程度上选择的约定。 这种区别很重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.