头文件在编译过程中的作用

来源:互联网 发布:社工数据库 编辑:程序博客网 时间:2024/05/01 07:08

头文件并不参加链接和编译。编译器第一步要做的就是简单的把头文件在包含它的源文件中展开。不知你是否能理解这句话。也就是头文件里面有什么内容,通通把它移到包含这个头文件的源文件里。(我觉得这是个很重要的概念,可以帮助我们简化理解编译链接的过程,包括理解头文件中定义静态变量或静态函数是怎么回事)。编译器经过这一步转换后剩下什么呢?就是一堆cpp文件了。而头文件已经不再是编译器需要关心的东西了。编译器接下来就要处理这一堆cpp文件了。


"头文件-源文件"的编译模型:
每个源文件作为一个编译单元,可能会包含上百甚至上千个头文件,而在每一个编译单元,这些头文件都会被从硬盘读进来一遍,然后被解析一遍。
每个编译单元都会产生一个obj文件,然后所以这些obj文件会被link到一起,并且这个过程很难并行。
这里,问题在于无数头文件的重复load与解析,以及密集的磁盘操作。


#ifndef只是防止了头文件被重复包含,但是无法防止变量被重复定义。

在其他文件中只要包含了xxx.h就会独立的解释,然后每个.c文件生成独立的标符。在编译器链接时,就会将工程中所有的符号整合在一起,由于文件中有重名变量,于是就出现了重复定义的错误


解决方法
.c文件中声明变量,然后建一个头文件(.h文件)在所有的变量声明前加上extern,注意这里不要对变量进行的初始化。然后在其他需要使用全局变量的.c文件中包含.h文件。编译器会为.c生成目标文件,然后链接时,如果该.c文件使用了全局变量,链接器就会链接到此.c文件 

注解:c/c++就这么规定:不可以在.h里定义变量,因为就是会触发这个重复定义错误。你只能在.h里用extern bool a;这样声明变量。

全局变量的定义就应当放在C文件里。然后在H文件里,用extern做外部声明。在需要用这个变量的源文件里包含上面这个H文件。

因为#include 是把后面的文件展开 就是static了,展开后还是两份它为每个include它的文件生成一份数据,
编译是对每个.cpp文件做的操作。

你这个重复定义可以通过编译, 但是在将多个.cpp编译出来的.obj文件链接成一个exe文件时就会有同一个变量在几个obj中都有定义, 这样就出错了, 链接器不知道到底该链接哪个定义的变量

#ifndef  GLOBAL_DEFINE  
#define  GLOBAL_DEFINE  
 
#endif 
// 这个只是用来防止Global.h被重复inlcude,在循环递归include中。只能防止你在一个源文件里,重复包含了头文件。

宏定义是局部有效的,就是在同一个编译单元中,也就是一个cpp文件。另外一个cpp文件再次判断#ifndef GLOBAL_DEFINE仍然会为TRUE。
你的情况是,有好几个源文件都各自包含了这个头文件,那么,当然,头文件里的变量就在几个源文件里都定义了
注解end
http://blog.sina.com.cn/s/blog_605f5b4f01018xeu.html

http://www.cnblogs.com/gcpopo/archive/2012/07/18/2598011.html

http://blog.csdn.net/luckyxiaoqiang/article/details/8957617