上一节介绍了使用C语言开发大型项目时如何开发多文件编程。
这个模块里定义了 add 函数,以后想使用 add 函数,只需要从 文件 extern add 函数即可。但是使用 模块的每个文件都需要重新声明 add 函数也是很麻烦的。前面的文章,我们一直强调重复的代码应该尽量避免,不仅仅 C 语言编程如此,其他大多编程语言也是类似的。
以前,我们都是把重复代码尽力封装为函数,增加代码复用性。那这次为了不重复声明模块里定义的函数,有什么办法呢?答案就是使用头文件。我们新建 文件,把 模块中能够提供给外界使用的函数或变量声明在头文件里,以后要使用这些函数或者变量,只需要包含头文件就可以了。请看:
//
#ifndef _FUN_H_
#define _FUN_H_
extern int add(int a, int b);
extern int cnt;
#endif // _FUN_H_
可以看出,如果想在 main.c 文件中使用 文件中定义的函数,只需要包含 就可以了。事实上,以后任何模块想调用 中的函数,都只需包含 即可。关于 中内容,有几点细节。
先再说说为什么 #include <;用角括号,而#include “”用引号。对于用尖括号包含的头文件,编译器会从系统的头文件目录查找。例如我的 codeblocks 的系统头文件路径:
对于引号包含的头文件,编译器会首先查找包含头文件的 .c 文件所在目录,没有找到再查找系统的头文件目录。因为我们建立的 文件和 main.c 在同一目录,所以在 main.c 文件中包含 头文件要用引号,如果用尖括号包含编译器就找不到 文件了,编译就会报错。
#ifndef _FUN_H_
#define _FUN_H_
//…
#endif
这几句属于条件编译语句,意思是如果没有 define FUN_H 就 define FUN_H ,如果之前 define 过,#ifndef 到 #endif 的代码段就不参与编译了,这样可以避免 #ifndef 到 #endif 的代码段被重复包含。在本例中,就是防止 add 和 cnt 的重复声明。FUN_H 当然也可以取其他名字,只需要确保唯一性就可以了。
那为什么需要防止重复包含呢?谁会把一个头文件包含两次呢?像上面那么明显的错误没人会犯,但有时候重复包含的错误并不是那么明显的。在规模较大的项目中头文件包含头文件的情况很常见,经常会包含四五层,这时候重复包含的问题就很难发现了。
比如在linux系统头文件目录/usr/include中,errno.h包含了bi,后者又包含了linux,后者又包含了asm,后者又包含了asm-generic。
另外一个问题是,就算我是重复包含了头文件,那有什么危害么?像上面的三个函数声明,在程序中声明两次也没有问题,对于 extern 的函数,声明任意多次也都代表同一个函数。重复包含头文件有以下问题:
- 一是使预处理的速度变慢了,要处理很多本来不需要处理的头文件。
- 二是如果有互相包含的情况,预处理器就陷入死循环了(其实编译器都会规定一个包含层数的上限)。
- 三是头文件里有些代码不允许重复出现,虽然变量和函数允许多次声明(只要不是多次定义就行),但头文件里有些代码是不允许多次出现的,比如typedef类型定义和结构体Tag定义等,在一个程序文件中只允许出现一次。
还有一个问题,为什么不直接包含 .c 文件呢? 我在 main.c 文件里直接 #include“”不更方便吗?当然,这样编译也能通过,可是以后要是又有一个模块需要用到 中定义的函数呢?再包含一次 ?这样不就相当于 add 函数有多处定义了吗?这样在程序链接阶段就会有麻烦,或者根本无法生成可执行程序。如果包含的是头文件,那无论包含多少次,add 函数也只有一处定义,链接是不会有问题的了。
欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。
1.文章《“c 如何创建一个头文件“vs如何创建头文件》援引自互联网,为网友投稿收集整理,仅供学习和研究使用,内容仅代表作者本人观点,与本网站无关,侵删请点击页脚联系方式。
2.文章《“c 如何创建一个头文件“vs如何创建头文件》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
相关推荐
- . 现代买票为什么带上携程保险
- . 潮阳怎么去广州南站
- . 湖南马拉河怎么样
- . 烧纸为什么到三岔路口
- . 百色为什么这么热
- . 神州租车怎么样
- . 芜湖方特哪个适合儿童
- . 护肤品保养液是什么类目
- . 早晚的护肤保养有哪些项目
- . 女孩护肤品怎么保养的最好