c源文件中为什么要包含自己对应的头文件
另一篇:.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源文件中为什么要包含自己对应的头文件的更多相关文章
- 一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?
可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致.
- 一个包含所有c++的头文件的头文件
#include <bits/stdc++.h> 做CF看见别人用这个函数,然后就能直接用vector,set,string那些函数了,摸不着头脑,感觉特神奇就百度了一下,才发现这个是C+ ...
- 【转】Eclipse中一键调用javah生成jni的头文件
这里定义了一个本地方法jni_test,该方法返回一个String.其中System.loadLibrary是用来加载本地库的(dll或者so). 有了这个类以后,就可以调用javac命令编译,得到E ...
- virtualbox linux客户机中安装增强功能包缺少kernel头文件问题解决
linux客户机中安装增强功能包总会提示缺少kernel头文件 根据发行版的不同,用命令行软件包管理命令安装dkms build-essential linux-headers-$(uname -r) ...
- 一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制
这个是可以的,一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致. 每个编译单元只能有一个public 类.这么做的意思是,每个编译单元只能有一个公开 ...
- kali 软件源 包含virtualbox所需头文件
# deb cdrom:[Debian GNU/Linux 7.0 _Kali_ - Official Snapshot i386 LIVE/INSTALL Binary 20130905-08:50 ...
- C++中头文件、源文件之间的区别与联系
.h头文件和.cpp文件的区别 疑惑1:.h文件能够编写main函数吗? 实验: 编写test.h文件,里面包含main函数 若直接编译g++ test.h -o test,通过file命令 file ...
- CPP-基础:内部函数应该在当前源文件中说明和定义
static函数与普通函数作用域不同,仅在本文件.只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义.对于可在当前源文件以外使用的函数,应该在一个头文件 ...
- C++中头文件与源文件的作用详解
一.C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件―― .cpp 文件和 .h 文件.其中,.cpp 文件被称作 C++ 源文件,里面放的都是 C++ 的源代码:而 .h 文件则被称作 ...
随机推荐
- python-can库基于PCAN-USB使用方法
一.概述 1.介绍 python-can库为Python提供了控制器局域网的支持,为不同的硬件设备提供了通用的抽象,并提供了一套实用程序,用于在CAN总线上发送和接收消息. 支持硬件接口: Name ...
- Python:GUI库tkinter(二)
学习自: Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) - 洪卫 - 博客园 Tkinter简明教程 - 知乎 TkDocs_官方文档 一个Tkinter库较为全面的总结,很 ...
- Vue之获取DOM元素与更新DOM后事件的特殊情况
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 01_c语言再学习_基础部分(1)
目录: 1.编译基础 2.c语言关键字 3.c语言数据类型 4.二进制/8进制/16进制 5.计算机内存数值存储方式:sizeof/原码/反码/补码 6.c语言中的字符和字符串 7.c语言中的数组和字 ...
- 矩池云利用ipykernel为JupyterLab添加kernel以及展示出来
source activate myconda pip install ipykernel python -m ipykernel install --user --name myconda --di ...
- phpstorm xdebug 断点测试
参考博客: https://blog.csdn.net/J2778322217/article/details/123111960?spm=1001.2014.3001.5502 https://no ...
- jq 简易购物车功能实现
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>& ...
- Vue的mvvm模式
传统的MVC模式: Model:模型-->负责数据存储 View:视图-->负责页面展示 Control:控制器-->事件交互(根据视图与用户交互后改变数据) Vue的MVVM模式: ...
- [Java编程思想] 第一章 对象导论
第一章 对象导论 "我们之所以将自然界分解,组织成各种概念,并按其含义分类,主要是因为我们是整个口语交流社会共同遵守的协定的参与者,这个协定以语言的形式固定下来--除非赞成这个协定中规定的有 ...
- 阿里一面,说说你了解zookeeper的应用场景有哪些?
1.前言 又到了金三银四的时候,大家都按耐不住内心的躁动,我在这里给大家分享下之前面试中遇到的一个知识点(zookeeper应用场景),希望对大家有些帮助.如有不足,欢迎大佬们指点指点. 2.zook ...