c语言头文件存放有要求吗,使用C语言中的头文件有什么技巧和注意事项吗?为什么不直接包含C文件呢?...

一般来说,C语言项目中的文件以其后缀名来看,常用的只有两种:*.c文件和 *. h 文件,后者常被称作“头文件”,因为这种类型的文件常常和 #include 关键字一起放在 *.c文件的头部, * . h 中的“h”常被认为是“header(头)”的缩写。

165314567_1_20190705044829472

大型C语言项目一般都是采用多文件编程的开发方式,fun.c模块里定义了 add() 函数,想在别的模块里使用 add() 函数,只需要从 fun.c 文件 extern add() 函数即可。关于 extern 关键字的介绍,可参考我的上一个回答。

但是使用 fun.c 模块的每个文件都需要重新声明 add() 函数也是很麻烦的。而且,在C语言程序开发中,重复的代码应该尽量避免。

在C语言程序开发中使用头文件

为了不重复声明 fun.c 模块里定义的函数,有什么办法呢?答案就是使用头文件。新建 fun.h 文件,把

fun.c模块中能够提供给外界使用的函数或变量声明在头文件里,以后要使用这些函数或者变量,只需要包含头文件就可以了。请看相关C语言代码:

165314567_2_20190705044829582

如果想在main.c文件中使用fun.c文件中定义的函数,只需要包含fun.h就可以了,下面是一段C语言代码例子,请看:

165314567_3_20190705044829660事实上,以后任何模块想调用fun.c中的函数,都只需包含fun.h即可。

关于fun.h中内容,有几点细节需要说明

先说说为什么 #include

165314567_4_20190705044829754

对于引号包含的头文件,C语言编译器会首先查找包含头文件的 .c 文件所在目录,没有找到再查找系统的头文件目录。

因为我们建立的 fun.h 文件和 main.c 在同一目录,所以在 main.c 文件中包含 fun.h 头文件要用引号,如果用尖括号包含编译器就找不到 fun.h 文件了,编译就会报错。

165314567_5_20190705044829832

避免头文件的重复包含

下面这几条C语言代码属于条件编译语句,意思是如果没有 define __FUN_H__ 就 define __FUN_H__ ,如果之前 define 过,#ifndef 到 #endif 的C语言代码段就不参与编译了,这样可以避免 #ifndef 到 #endif 的代码段被重复包含。__FUN_H__ 当然也可以改成其他名字,只需要确保唯一性就可以了。

165314567_6_20190705044829925

那为什么需要防止重复包含呢?谁会把一个头文件包含两次呢?像上面那么明显的错误没人会犯,但有时候重复包含的错误并不是那么明显的。

在规模较大的C语言项目中头文件包含头文件的情况很常见,经常会包含四五层,这时候重复包含的问题就很难发现了。比如在我的系统头文件录/usr/include中,errno.h包含了bits/errno.h,后者又包含了linux/errno.h,后者又包含了asm/errno.h,后者又包含了asm-generic/errno.h。

165314567_7_20190705044829988另外一个问题是,就算我是重复包含了头文件,那有什么危害么?像上面的三个函数声明,在C语言程序中声明两次也没有问题,对于具有External Linkage的函数,声明任意多次也都代表同一个函数。在C语言项目中重复包含头文件有以下问题:一是使预处理的速度变慢了,要处理很多本来不需要处理的头文件。

二是如果有互相包含的情况,预处理器就陷入死循环了(不过现在编译器都会规定一个包含层数的上限)。

三是头文件里有些C语言代码不允许重复出现,虽然变量和函数允许多次声明(只要不是多次定义就行),但头文件里有些C语言代码是不允许多次出现的,比如typedef类型定义和结构体Tag定义等,在一个程序文件中只允许出现一次。

165314567_8_2019070504483097

还有一个问题,为什么不直接包含 .c 文件呢?

我在 main.c 文件里直接 #include “fun.c” 不更方便吗?当然,这样的C语言代码编译也能通过,可是以后要是又有一个模块需要用到 fun.c 中定义的函数呢?再包含一次 fun.c ?这样不就相当于 add() 函数有多处定义了吗?这样在程序链接阶段就会有麻烦,或者根本无法生成可执行程序。如果包含的是头文件,那无论包含多少次,add() 函数也只有一处定义,链接是不会有问题的了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值