另一篇:.c文件和.h文件的关系

引言:

我们经常在c工程中发现,源文件中要包含自己的头文件。一直以来,都不知道为什么这样做。现在,我知道了。

以前的认知:

我认为,.c文件没有必要包含自己的.h文件。.h文件包含.c文件中定义的函数和全局变量的声明,.h文件就是.c文件提供的对外接口文件。既然.h文件就是.c文件提供的对外接口文件,那么.c文件就没必要包含自己的.h文件了(.h文件是对外提供用的,对内又何必再包含进来呢)。

鉴于这样的理解,我对于工程中.c源文件包含自己的.h头文件很是不理解,不知道为什么要这样做。

现在对此的理解:

但是现在,我知道为什么要源文件包含自己的头文件了。

如下,一段书中的原话:

“如果希望让编译器检查声明的一致性,一定要把全局声明放到头文件中。特别是,永远不要把外部函数的原型(也就是函数声明)放到.c文件中:通常它与定义的一致性不能得到检查,而矛盾的原型(也就是函数声明)比不用还糟糕。”

注意:外部函数的原型,就是外部函数的声明。

对这段话的理解:

为什么:“永远不要把外部函数的原型放到.c 文件中”

这个外部函数A指的是B.c文件之外定义的函数,B.c文件中需要使用外部函数A,就需要先对外部函数A声明(对外部函数的声明就是外部函数原型)。对这个外部函数A的声明,不能放在B.c文件里面来实现。

以实例说明:

①假若工程中有2个源文件a.c和b.c;a.c的头文件为a.h,b.c的头文件为b.h。

②a.c中定义了一个函数sum。

③b.c要引用sum这个函数。做法是:在b.c中声明sum这个函数。然后b.c就可以使用sum函数了。

这样的做法就是把外部函数sum的声明放到了b.c中来。然而,这样的做法很不妥。

不妥的原因:

sum是在a.c中定义的,而声明确是在b.c中,sum函数的定义和声明不是在同一个文件中的。定义和声明不在同一个文件中,编译的时候,编译器就不能对定义和声明的一致性进行检查。这样,如果sum的定义和声明不一致,编译器就无法检查出来(定义和声明不在同一个文件中),那么编译的时候不会报错,但是程序运行的时候就可能会出错。而这样的错误,查找起来又不是很容易。

鉴于此,才这样说:“永远不要把外部函数的原型放到.c文件中”。

那如何才能让编译器检查定义和声明的一致性呢?

前面说,如果把外部函数的原型放到.c文件中,编译器就无法检查声明和定义的一致性(声明和定义不在同一个文件中)。那么,要让编译器检查定义和声明的一致性呢,自然是把定义和声明放在同一个文件中,而如何实现把定义和声明放在同一个文件里呢?

答案:源文件定义的函数,在源文件对应的头文件中声明,然后源文件包含自己的头文件。这样定义和声明就放在同一个文件里了。

援引上述例子:a.c中定义了函数sum,而函数本质上是外部的,函数sum是可以被其它源文件调用的。那么,我们把sum函数的声明放在a.h中。然后a.c源文件还要包含自己的头文件,也就是a.h文件。而b.c文件要引用sum函数,就直接包含a.h文件就可以。

sum函数的定义在a.c中,声明是在a.h中,但是由于a.c包含了a.h,所以sum的定义和声明就是在同一个文件a.c中了。这样,编译器编译的时候,就能对sum函数定义和声明的一致性做检查,如果不一致,就会报错。

至于其他源文件引用这个外部函数sum,不再采用直接声明的方式,而是通过包含a.h头文件的方式。

这样,编译器检查了sum函数定义和声明的一致性没有报错,也就表明a.c中sum函数的定义和a.h中sum函数的声明是一致的。那么其他源文件都是通过直接包含a.h,来使用函数sum,就也保证了sum函数声明和定义的一致性了。

结论

c源文件要包含自己的头文件,目的就是让编译器检查定义和声明的一致性。

转自:https://blog.csdn.net/khwkhwkhw/article/details/49798985

c源文件中为什么要包含自己对应的头文件的更多相关文章

  1. 一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?

    可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致.

  2. 一个包含所有c++的头文件的头文件

    #include <bits/stdc++.h> 做CF看见别人用这个函数,然后就能直接用vector,set,string那些函数了,摸不着头脑,感觉特神奇就百度了一下,才发现这个是C+ ...

  3. 【转】Eclipse中一键调用javah生成jni的头文件

    这里定义了一个本地方法jni_test,该方法返回一个String.其中System.loadLibrary是用来加载本地库的(dll或者so). 有了这个类以后,就可以调用javac命令编译,得到E ...

  4. virtualbox linux客户机中安装增强功能包缺少kernel头文件问题解决

    linux客户机中安装增强功能包总会提示缺少kernel头文件 根据发行版的不同,用命令行软件包管理命令安装dkms build-essential linux-headers-$(uname -r) ...

  5. 一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制

    这个是可以的,一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致. 每个编译单元只能有一个public 类.这么做的意思是,每个编译单元只能有一个公开 ...

  6. kali 软件源 包含virtualbox所需头文件

    # deb cdrom:[Debian GNU/Linux 7.0 _Kali_ - Official Snapshot i386 LIVE/INSTALL Binary 20130905-08:50 ...

  7. C++中头文件、源文件之间的区别与联系

    .h头文件和.cpp文件的区别 疑惑1:.h文件能够编写main函数吗? 实验: 编写test.h文件,里面包含main函数 若直接编译g++ test.h -o test,通过file命令 file ...

  8. CPP-基础:内部函数应该在当前源文件中说明和定义

    static函数与普通函数作用域不同,仅在本文件.只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义.对于可在当前源文件以外使用的函数,应该在一个头文件 ...

  9. C++中头文件与源文件的作用详解

    一.C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件―― .cpp 文件和 .h 文件.其中,.cpp 文件被称作 C++ 源文件,里面放的都是 C++ 的源代码:而 .h 文件则被称作 ...

随机推荐

  1. WPS:字母自动变大写的解决办法

    设置中:

  2. docker学习笔记(1)- 架构概述

    微服务架构 微服务VS传统分层架构 传统分层架构 优点 对于简单系统: 容易部署 容易测试 容易横向扩展 缺点 对于复杂系统: 耦合度高 不易快速维护 启动慢,部署慢 模块变更引起的回归问题多 难以持 ...

  3. Java 将XML转为PDF

    可扩展标记语言(XML)文件是一种标准的文本文件,它使用特定的标记来描述文档的结构以及其他特性.通过将XML转换为PDF,能够便于文件传输及共享.本文,将介绍通过Java代码来实现该格式转换的方法. ...

  4. Lua中如何实现类似gdb的断点调试--04优化钩子事件处理

    在第一篇的01最小实现中,我们实现了一个断点调试的最小实现,在设置钩子函数时只加了line事件,显然这会对性能有很大的影响.而后来两篇02通用变量打印和03通用变量修改及调用栈回溯则是提供了一些辅助的 ...

  5. Python中的super().__init__()

    Python里的super().init()有什么用? 简单的说super().__init__(),就是继承父类的init方法,同样可以使用super()去继承其他方法. 下面是三种不同的继承.调用 ...

  6. nginx 访问php文件报错

    问题图: An error occurred. 解决方法(windows版) php.cgi没有启动 cmd中找到cig.exe 的位置然后运行   php-cgi.exe -b 127.0.0.1: ...

  7. springboot Redistemplate的execute和 executePipelined

    springboot 的 RedisTemplate 的 execute 和 executePipelined 功能的区别 1.execute 以下是 springboot 官网原文: Redis p ...

  8. ArcMap从建库到出图

    1前言 本篇博主将介绍关于ArcMap建库.数据采集.拓扑检查.图表.制作符号等的基本操作. 2问题阐述 (1)检查现有block(线要素)图层,保证所有要素闭合,并将其转换为parcel(面要素): ...

  9. 微信Native支付

    微信Native支付对接(扫码) 由于有业务需求对接了微信和paypal支付,这边做个记录 微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/index. ...

  10. Redhat7 安装 yum源(亲测有效)

    由于之前安装Redhat7 想安装vsftpd  使用yum   install vsftpd 报错: This system is not registered to Red Hat Subscri ...