VC include 路径解析
要了解vc中使用#include命令包含头文件所搜寻的路径,必须先了解vc中的几种路径:
1. 系统路径
系统路径在vc中是"Tools->Options->Directories"中"Include files"指定的路径。
打开此对话框会发现默认有这几条路径:
C:Program FilesMicrosoft Visual StudioVC98INCLUDE
C:Program FilesMicrosoft Visual StudioVC98MFCINCLUDE
C:Program FilesMicrosoft Visual StudioVC98ATLINCLUDE
我们可以在这里添加,这样我们自己添加的路径也会成为系统路径。添加的格式必须按照上面来写。
2. 当前路径
当前路径是指.cpp文件所在路径,而不是网上有网友说的vc的工程文件(vc6.0为.dsw; vc2008为.vcproj)
3. 附加路径
附加路径是指在"Project->Settings->C/C++->Preprocessor->Additional include directories "中指定的路径。在vc2008中,指的是在工程属性中的包含的路径。
此路径默认为空,我们可以在此处填写需要路径,比如:在此处填入"C:123",(不要引号),那么附加路径就会变成"C:123" 。这里也可以根据“编辑”选项里面的宏定义进行替换。
上面的1,3路径,我们均可以自己编辑。在编辑过程中,可以使用绝对路径,也可以使用相对路径。
比如,在添加系统路径时,可以这样填写:(.表示当前路径;..表示上一层目录)
.SRC 这样写表示,当前目录中的SRC文件夹;
..SRC 这样写表示,当前目录的上一层目录中SRC文件夹;
...SRC 这样写表示,当前目录下 ..SRC\ 路径,当然这种写法已经和第一种重叠了。
这种相对路径的写法,vc会自动帮我们转化为绝对路径。
在添加附加路径时,其相对路径的写法和系统路径是一致的。
在vc中使用#include 命令,有三种形式:
1. #include <file.h>
vc执行这条指令时,它会在系统目录中去查找 file.h 文件。在此条码命令中,vc不会去当前路径和附加路径中查找文件。
2. #include "file.h"
vc执行这条指令时,依次搜索第一,第二,第三,找到了就不继续往下搜索。
第一,搜索用到该头文件(#include "file.h")的.cpp文件所在路径,即当前路径;(以.cpp文件为参考点进行搜索)
第二,搜索附加路径+include好面括号里面的文件。例如,附加路径为:"D: est", 则,第二步就搜索
"D: estfile.h";(在生成的绝对路径中搜索.h文件)
第三,搜索系统路径;(在系统路径下搜索.h文件)
3. #include "directoryfile.h"
vc执行这条指令时,依次搜索第一,第二,第三,找到了就不继续往下搜索。
第一,搜索当前路径(用到该头文件(#include "file.h")的.cpp文件所在路径)是否有一个directory文件夹,如果有,则搜索该文件夹子下是否有file.h文件。
第二,搜索附加路径+include好面括号里面的文件。例如,附加路径为:"D: est", 则,第二步就搜索
"D: estdirectoryfile.h";
第三,搜索系统路径。
总结:VC中的include的路径问题困扰了我很长一段时间,经过写测试实例验证后,发现了如上的规律。其中,把握include的路径问题,主要是要把握相对的文件是哪个,例如,当前路径,指的就是“用到头文件的cpp文件的路径”;而附加路径,则一定要和include里面的文件相结合,形成一个绝对路径。非常需要注意的一点就是,include的路径问题,与工程文件(.dsw和.vcproj)一点关系都没有。
头文件如何来关联源文件?<!--[endif]--> 这个问题实际上是说,已知头文件“a.h”声明了一系列函数,“b.cpp”中实现了这些函数,那么如果我想在“c.cpp”中使用“a.h”中声明的这些在“b.cpp”中实现的函数,通常都是在“c.cpp”中使用#include “a.h”,那么c.cpp是怎样找到b.cpp中的实现呢?
其实.cpp和.h文件名称没有任何直接关系,很多编译器都可以接受其他扩展名。比如偶现在看到偶们公司的源代码,.cpp文件由.cc文件替代了。 在Turbo C中,采用命令行方式进行编译,命令行参数为文件的名称,默认的是.cpp和.h,但是也可以自定义为.xxx等等。 谭浩强老师的《C程序设计》一书中提到,编译器预处理时,要对#include命令进行“文件包含处理”:将file2.c的全部内容复制到#include “file2.c”处。这也正说明了,为什么很多编译器并不care到底这个文件的后缀名是什么----因为#include预处理就是完成了一个“复制并插入代码”的工作。 编译的时候,并不会去找b.cpp文件中的函数实现,只有在link的时候才进行这个工作。我们在b.cpp或c.cpp中用#include “a.h”实际上是引入相关声明,使得编译可以通过,程序并不关心实现是在哪里,是怎么实现的。源文件编译后成生了目标文件(.o或.obj文件),目标文件中,这些函数和变量就视作一个个符号。在link的时候,需要在makefile里面说明需要连接哪个.o或.obj文件(在这里是b.cpp生成的.o或.obj文件),此时,连接器会去这个.o或.obj文件中找在b.cpp中实现的函数,再把他们build到makefile中指定的那个可以执行文件中。 在Unix下,甚至可以不在源文件中包括头文件,只需要在makefile中指名即可(不过这样大大降低了程序可读性,是个不好的习惯哦^_^)。在VC中,一帮情况下不需要自己写makefile,只需要将需要的文件都包括在project中,VC会自动帮你把makefile写好。 通常,编译器会在每个.o或.obj文件中都去找一下所需要的符号,而不是只在某个文件中找或者说找到一个就不找了。因此,如果在几个不同文件中实现了同一个函数,或者定义了同一个全局变量,链接的时候就会提示“redefined”。