• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 详解C 语言项目中.h文件和.c文件的关系

详解C 语言项目中.h文件和.c文件的关系

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c语言指针详解,c语言题库及详解答案,vhdl语言100例详解,c语言关键字详解,c语言链表详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

详解C 语言项目中.h文件和.c文件的关系

在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件。但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件。

    于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句。这样即使某个声明发生了变更,也再不需要到处寻找与修改了。因为这个新文件,经常被放在.c(.cpp)文件的头部,所以就给它起名叫做“头文件”,扩展名是.h。

    在我们语言的初学阶段,往往我们的程序只有一个.c的文件或这很少的几个,这时我们就很少遇到头文件组织这个头疼的问题,随着我们程序的增加,代码 量到了几千行甚至几万行,文件数也越来越多。这时这些文件的组织就成了一个问题,其实说白了这些文件的组织问题从理论上来说是软件工程中的模块设计等等的问题。

    头文件的作用的简短描述:

(1)通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。
(2)头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。

    比方说 我在aaa.h里定义了一个函数的声明,然后我在aaa.h的同一个目录下建立aaa.c , aaa.c里定义了这个函数的实现,然后是在main函数所在.c文件里#include这个aaa.h  然后我就可以使用这个函数了。 main在运行时就会找到这个定义了这个函数的aaa.c文件。这是因为:main函数为标准C/C++的程序入口,编译器会先找到该函数所在的文件。假定编译程序编译myproj.c(其中含main())时,发现它include了mylib.h(其中声明了函数void test()),那么此时编译器将按照事先设定的路径(Include路径列表及代码文件所在的路径)查找与之同名的实现文件(扩展名为.cpp或.c,此例中为mylib.c),如果找到该文件,并在其中找到该函数(此例中为void test())的实现代码,则继续编译;如果在指定目录找不到实现文件,或者在该文件及后续的各include文件中未找到实现代码,则返回一个编译错误.其实include的过程完全可以“看成”是一个文件拼接的过程,将声明和实现分别写在头文件及C文件中,或者将二者同时写在头文件中,理论上没有本质的区别。

    理论上来说C文件与头文件里的内容,只要是C语言所支持的,无论写什么都可以的,比如你在头文件中写函数体,只要在任何一个C文件包含此头文件就可以将这个函数编译成目标文件的一部分(编译是以C文件为单位的,如果不在任何C文件中包含此头文件的话,这段代码就形同虚设),你可以在C文件中进行函数声明,变量声明,结构体声明,这也不成问题!!!那为何一定要分成头文件与C文件呢?又为何一般都在头件中进行函数,变量声明,宏声明,结构体声明呢?而在C文件中去进行变量定义,函数实现呢??

   要理解C文件与头文件有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:

1.预处理阶段
2.词法与语法分析阶段
3.编译阶段,首先编译成纯汇编语句,再将之汇编成跟CPU相关的二进制码,生成各个目标文件
4.连接阶段,将各个目标文件中的各段代码进行绝对地址定位,生成跟特定平台相关的可执行文件,编译器在编译时是以C文件为单位进行的,也就是说如果你的项目中一个C文件都没有,那么你的项目将无法编译,连接器是以目标文件为单位,它将一个或多个目标文件进行函数与变量的重定位,生成最终的可执行文件,在PC上的程序开发,一般都有一个main函数,这是各个编译器的约定。为了生成一个最终的可执行文件,就需要一些目标文件,也就是需要C文件,而这些C文件中又需要一个main函数作为可执行程序的入口。 

    简单些说就是C语言的编译分为预处理、编译、汇编、链接(test.c test.h => test.i => test.s => test.o => test)四个大的阶段。c文件中的#include宏处理,会在预处理的阶段将c中引用的h文件的内容全部写到c文件中,最后生成.i中间文件,这时h 文件中的内容就相当于被写道c文件中。这也为代码的复用提供了渠道,很多的c文件可以去引用同一个h文件,这样这个h文件就会被放到多个c文件中被编译多 次,这也是h文件中不能放定义只能放声明的原因,放定义时被编译多次,在程序链接的时候(系统中定义了多个int a;强符号定义)会出现错误, 声明就不一样,声明表示对定义的扩展,最终都会终结到一个定义上,所以不会出现link时重复定义的错误。 

编程中我们在h文件中肯定都用过一下的格式

#ifndef  XXX_H
#define  XXX_H
 //……
#endif
</div>

呵呵,那他到底有什么用呢,在h文件互相引用时,消除重复定义。当然宏定义是在预处理阶段发挥作用的,编译方后的过程是没有宏的影子的。

A.h
int a();
 
B.h
#include "A.h"
 
C.h
#include "A.h"
 
D.h
#include "A.h"
#include "B.h"
</div>

上面的D.h文件中就会重复出现两个int a();的声明阿,这样就有点重复了,这时条件编译宏就派上了用场

A.h
#ifndef A_H
#define A_H
int a();
#endif
</div>

这样就不会重复定义了。

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C语言中条件编译详解
  • C语言中强制地址跳转详解
  • 详解C 语言项目中.h文件和.c文件的关系
  • C语言中 值传递和指针传递实例详解
  • 详解C语言中的函数、数组与指针
  • C语言 坐标移动详解及实例代码
  • 详解C语言中的字符串拼接(堆与栈)
  • C语言 经典题目螺旋矩阵 实例详解
  • C语言 文件操作解析详解及实例代码
  • C语言 冒泡排序算法详解及实例

相关文章

  • 2017-05-28C++设计类不能被继承的方法实例讲解
  • 2017-05-28C/C++动态分配与释放内存的区别详细解析
  • 2017-05-28C++重载运算符的规则详解
  • 2017-05-28C++实现二叉树遍历序列的求解方法
  • 2017-05-28C++实现打印1到最大的n位数
  • 2017-05-28VC解析XML文件-CMarkup的使用详解
  • 2017-05-28c语言中使用BF-KMP算法实例
  • 2017-05-28c/c++输出重定向的方法
  • 2017-05-28C++中对象的常引用总结
  • 2017-08-17C和C++的内存操作小贴士(一):const char*的内存释放问题

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C语言实现顺序表基本操作汇总
    • 老生常谈C语言静态函数库的制作和使用
    • 深入java线程池的使用详解
    • C语言中的strdup()函数和其与strcpy()函数的区别
    • 探讨编写int strlen(char *strDest);不允许定义变量的问题
    • 解析C/C++中如何终止线程的运行
    • C语言中的小数(float,double)
    • C语言中二维数组指针的简要说明
    • 详解C语言中symlink()函数和readlink()函数的使用
    • c语言获取直播吧最近一周nba比赛信息

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有