c语言包含头文件中,#include中包含的文件是什么?头文件还是源文件

6043人阅读
C/C++(8)
随着代码越写越长,一个源文件的体制越来越臃肿。于是提倡将代码写到不同的多个源文件中去。将代码写到多个源文件中去就会遇到各个源文件中函数与变量的调用规则问题。
通常人们习惯性的把宏定义、结构体、联合体、枚举、外部变量和外部函数声明等写入到头文件.h中去,而把函数的声明、变量定义等写入到.c文件中去。当某一.c源文件需要调用某一函数的时候,只要将包含这个函数声明的头文件包含到本文件中来就可以了。如a.h中声明了a.c中定义的fun()函数,而b.c需要fun()函数,只需要#include ”a.h”就可以了。B.c怎么找到fun()的呢,难道a.c和a.h间通过同名建立了一种联系,b.c会直接到a.c中去寻找fun()?
很多时候,人们习惯性的把一个源文件中的宏定义、结构体、联合体、枚举、外部变量和外部函数声明等写入到一个同名的头文件中去。这给人的错觉就是同名使得两者被关联起来,在b.c包含a.h时,会自动去a.c中去寻找fun()函数。其实不然。
再给一个例子,如a.h中声明了b.c中定义的fun()函数,而c.c需要fun()函数,只需要#include”a.h”就可以了。这个例子就说明,不是同名的头文件也可以用来声明源文件中的函数等。那怎么通过头文件寻找到函数定义呢?
原理要从编译器工作过程说起。编译器工作过程分为4步骤:
1预处理阶段&:以c源文件为单位,处理宏替换、条件编译和文件包含。预处理本质上就是代码文本的替换。拿头文件包含来说,就是把包含的头文件中的所有代码copy到源文件中去。于是就形成了一个“中间c文件”。
2语法分析阶段&:c语言语法分析,你懂得。
3编译阶段:以“中间c文件”为单位,首先编译成纯汇编语句,再将之汇编成跟CPU相关的二进制码,生成各个目标文件 (.obj文件)。编译阶段不会去寻找用到的头文件中的函数的定义,只是按照一定规格转换代码格式为二进制。
4连接阶段:将上一步成生的各个目标文件,根据一些参数,连接生成最终的可执行文件。主要的工作就是重定位各个目标文件的函数,变量等。
我们在b.c或c.c中用#include “a.h”实际上是引入相关声明,使得编译可以通过,程序并不关心实现是在哪里,是怎么实现的。源文件编译后成生了目标文件(.o或.obj文件),目标文件中,这些函数和变量就视作一个个符号。在link的时候,需要在makefile里面说明需要连接哪个.o或.obj文件(在这里是b.c生成的.o或.obj文件),此时,连接器会去这个.o或.obj文件中找在c.c中实现的函数,再把他们build到makefile中指定的那个可以执行文件中。通常,编译器会在每个.o或.obj文件中都去找一下所需要的符号,而不是只在某个文件中找或者说找到一个就不找了。因此,如果在几个不同源文件中都包含了同一个头文件,该头文件中的某些变量默认地就会被编译超过一次,链接的时候就会提示“redefined”。这也就解释了重定义一般不会在编译阶段出错,而会在链接阶段出错。
总结出来一句话:源文件调用#inlude头文件中的函数不是通过直接查找同名源文件找到的,而是通过逐个查找已经编译好的.o或者.obj找到的。但是还是建议使用同名的源文件和头文件,这样便于形成模块化,使代码清晰易懂,便于打理。
编译器的编译过程告诉我们另外一个写头文件需要注意的地方,头文件的预编译在插入有用代码的同时也会插入大量不需要的东西,一个头文件被多个源文件包含还会出现重定义的问题。这些都是需要注意的。插入了不需要的东西在很大程度上是不可避免的,但是精简了代码,看起来简洁了不少。我们可以把那些经常在一起使用的宏定义、声明等放在一个头文件中,减少不必要的公用。关于重定义,可以通过#ifndef #define #endif来解决。下面以一个例子来说明。
假设有三个文件
&node.h //定义节点
list.h //对链表的操作函数
test.c //测试函数
包含关系如下:
#include&node.h&
#include&list.h&
#include&node.h&
#include ... 省略其它必要的头文件
使用命令编译
$gcc -o testtest.c
编译时,会出现错误:XXX重定义
为什么呢?
1)test.c中包含了node.h,因为node.h是定义结构的文件,而且已经被list.h包含了,所以这里node.h会预编译两次,出现重定义!
所以,可以去掉test.c中的头文件node.h即可
2)修改node.h,避免重定义,这种方法也是推荐的方法
#ifndef _NODE
#define _NODE
typedef struct node{
struct node*
使用一个标记变量_NODE来表示NODE结构已经被定义了,将定义过程包含在#ifndef~#endif中,这样,不管包含多少次node.h文件,都不会出现重定义。
当然,这不仅仅限于结构的定义。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:19958次
排名:千里之外
原创:10篇
(1)(1)(4)(5)(1)(2)12:36 提问
C语言头文件里放声明,其实现放哪?
我写了一个头文件a.h,实现在a.c中,主文件中#include "a.h",报错。。。我想知道头文件的声明和定义的规范使用方法。。谢谢。。
按赞数排序
首先搞清楚,include和头文件的关系。
include的作用是将这个文件的内容插入到include所在的位置,从而构成一个完整的源代码文件被编译。
那么头文件是什么,实际上头文件里可以放任何东西,源代码文件也可以放任何东西,include也可以随意包含。
只是看这三者放在一起,经过替换,得到的源代码最终是否成立。
C要求函数先声明,再使用,所以如果函数被很多源代码同时使用,那么为了减少麻烦(每个文件都必须把函数原型写一遍),就把它们集中起来写在头文件中,每个源代码去include
这是头文件的作用。
回到你的问题,实现放在哪里,按理说放在哪里都可以,但是从最能体现头文件的意义和使用价值的角度来说,应该放在一个单独的源代码文件中。
你将鼠标的光标放在你需要知道的头文件上,然后按【ctrl+鼠标左键】就能跳到那个头文件里定义的界面了;
其它的都是一样的,将鼠标光标移到你要查看的方法或类上,按【ctrl+鼠标左键】;
这个快捷键你最好记住,能省不少麻烦
如果回答对您有帮助,请采纳
a.c中有没有包含那个头文件
好多的大神给出了精彩的回复:对于你的问题,给出两个答复:一个是本身自带库文件,一个是你自己创建的.h文件。
include(studio.h);
include(studio.h);
a.h文件里给出声明,在a,c里实现函数,然后在其他.c文件里加上#include后就可以直接调用了
a.h放声明,a.c放实现,a.c和main.c都要#include"a.h"
不知道你是什么错误,放出来看看把。
#include”a.h"就相当于在这个位置插入a.h这个文件的内容。
与头文件同名的源文件内进行实现
228关注|280收录
42关注|57收录
395关注|2288收录
其他相似问题
相关参考资料c语言中,#include中包含的文件是什么?头文件还是源文件_百度知道
c语言中,#include中包含的文件是什么?头文件还是源文件
再编译, 也可以 包含 源文件#include
宏命令#include
可包含 头文件,在编译前,在此位置 嵌入 一个文件 的内容, 嵌入后,它告诉编译器
其他类似问题
为您推荐:
其他3条回答
包含一个.h的文件都是可行的#include就是把一个文件里的所有内容包含进来,不过一般都是包含的头文件.c的文件和一个
C/C++等一些语言在运行时需要导入需要的库,常用的比如stdio.h, 如果代码中需要数学运算符比如开方sqrt函数,就要导入数学库math.h,每个库都有自己特殊的函数,看你的程序需求。
当然是头文件啦,一般头文件中的函数都有在文件中定义的。
必须用.h作为扩展名?
这个不是必须的,.h只是一种习惯
头文件的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁C语言中新建一个C/C++头文件和一个与C/C++源文件有什么区别?_百度知道
C语言中新建一个C/C++头文件和一个与C/C++源文件有什么区别?
1、相同点:头文件与源代码都是源文件,都用纯文本文件存储,都需要遵照C/C++语言规范来写,都可以使用类型定义和常、变量定义,都可以包含函数的声明和实现,都能包含宏定义,都使用相同的调用规范。2、不同点:C/C++的编译器规定源代码文件必须包含函数入口,即main函数,或者winmain函数。而头文件不得包含函数入口,也就是说,头文件不可以单独编译成一个程序,仅仅包含程序片断或者仅仅定义常、变量。3、关联:头文件是专为源代码调用而写的静态包含文件,可被源代码文件中的#include编译预处理指令解释,而将头文件完整拷贝到源代码的指令处,从而在编译时相当于在源代码中插入了函数声明或者实现。某些头文件包含了静态库中的函数调用声明,包含了LIB文件的调用信息,编译时静态链接进程序;而某些头文件是专为方便API调用而写的,里面包含了动态链接库的调用信息和规范,只有在运行时将DLL载入内存提取函数执行。也就是说,其实你将头文件里的信息完全写到源代码里,是可以实现完全相同的功能的。如果想要学写头文件,可以参照标准C/C++库的h文件。
其他类似问题
为您推荐:
头文件的相关知识
其他2条回答
没有区别,类定义放在头文件中哗揣糕废蕹肚革莎宫极,类的实现放在源文件中,类的实现也可以放在头文件中,这样做只是方便管理和维护。
没什么区别,在编译时都一样只不过头文件需要引用才可以使用
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 c语言头文件和源文件 的文章

 

随机推荐