头文件与同名源文件的关系
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
一、头文件寻找路径
1,系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。
#include <xxx.h>2,用户自定义的文件用双引号括起来,编译器首先会在用户目录下查找,然后在到C++安装目录(比如VC中可以指定和修改库文件查找路径,Unix和Linux中可以通过环境变量来设定)中查找,最后在系统文件中查找。
#include “xxx.h”
二、头文件如何来关联源文件
这个问题实际上是说,已知头文件“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”。
请问C语言头文件.h和.c的关系
如果在C文件(比如miset.c)中定义了一个函数,在其相应的h文件(miset.h)中声明,那为什么在其他文件中只要include该h文件(miset.h)时就能找到该函数呢,同时如果把这个函数的声明放在另外一个头文件miphone.h中,而在包含该头文件miphone.h时为什么又找不到该函数呢。头文件和C文件时如何一一对应起来的呢?为什么该C文件定义的函数声明只能放在和他名字一样的头文件中?求教
回复于: 2011-07-15 18:50:55
其实这一切都有集成开发工具帮你做了。
如果用make命令来自己控制编译过程,事情很明白了。
比如aaa.h 和 aaa.cpp 定义了函数 int test(void)
mian.cpp 含有对test函数的引用。
首先编译每一个.cpp文件,生成对应的.obj文件。
在编译的过程中对于调用的函数并不需要具体的实现,只要知道函数的原型即可,在函数调用的地方生成一个引用符号。
链接的时候需要找到引用符号的实现。
link main.obj aaa.obj 此时编译器要在main.obj、aaa.obj中查找test的实现。
如果只 link main.obj 此时编译器会提示一个错误找不到test符号什么的。
编译和链接的过程由集成开发环境自动生成。
标注库文件只需要引用头文件,链接的时候编译器自动查找对应的.lib
自己的库,不但在源码中包含头文件,在链接时还要指明库文件。
如果用make命令来自己控制编译过程,事情很明白了。
比如aaa.h 和 aaa.cpp 定义了函数 int test(void)
mian.cpp 含有对test函数的引用。
首先编译每一个.cpp文件,生成对应的.obj文件。
在编译的过程中对于调用的函数并不需要具体的实现,只要知道函数的原型即可,在函数调用的地方生成一个引用符号。
链接的时候需要找到引用符号的实现。
link main.obj aaa.obj 此时编译器要在main.obj、aaa.obj中查找test的实现。
如果只 link main.obj 此时编译器会提示一个错误找不到test符号什么的。
编译和链接的过程由集成开发环境自动生成。
标注库文件只需要引用头文件,链接的时候编译器自动查找对应的.lib
自己的库,不但在源码中包含头文件,在链接时还要指明库文件。
回复于: 2011-07-15 23:24:27
1楼有一个小错误,就是link过程是由链接器完成的。make只针对一个编译单元(.c),对其中的预处理后编译。这个过程中.h会在引用处直接展开。make不需要知道文件之间更多的关系。链接过程中,链接器会根据引用的函数原型,去寻找函数的实现,并把它们联系起来。
回复于: 2011-07-19 11:46:30
c文件与h文件没有直接联系,h文件声明符号,c文件定义符号。在编译的过程中,编译器只查看符号声明,在链接过程中,链接器查找符号定义。所以,你编译程序时只需要引用头文件,你在链接的时候,你要提供obj文件。
另外你说无法找到函数定义,是因为你没有提供能够找到函数定义的obj文件。无论在哪里声明,在链接的时候,只要你提供含有函数定义的obj、lib文件,都可以进行编译链接,文件名之间没有直接的联系!
不知道你懂了没有?
另外你说无法找到函数定义,是因为你没有提供能够找到函数定义的obj文件。无论在哪里声明,在链接的时候,只要你提供含有函数定义的obj、lib文件,都可以进行编译链接,文件名之间没有直接的联系!
不知道你懂了没有?
这本书建议有半年以上编程经验之后再看,内容较深,但对调试程序有很多好处。
总结
c文件和h文件没有必然关系,两个文件名可以不同名,h文件也能声明c文件中的函数,然后在main中包含h文件,然后使者h中声明的函数。
但前提是Makefile中有生成c文件对应o文件的规则,因为在链接成目标的时候,通过在指定目录中按照函数标识在o文件中寻找的。
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献16条内容
所有评论(0)