c头文件(.h)的作用
C语言的著作中,至今还没发现把.h文件的用法写的透彻的。在实际应用中也只能依葫芦画瓢,只知其然不知其所以然,甚是郁闷!闲来无事,便将搜集网络的相关内容整理一下,以便加深自己的理解
理论概述:
.h中一般放的是同名.c文件中定义的变量、数组、函数的声明,需要让.c外部使用的声明。
1)h文件作用:
1.方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明;
2. 使函数的作用域从函数声明的位置开始,而不是函数定义的位置(实践总结)
3 .提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h)。
2)h文件里应该有什么:常量,结构,类型定义,函数,变量申明。
3)h文件不应该有什么:变量定义, 函数定义。
4)extern问题:
1.对于变量需要extern;
2.对于函数不需要因为函数的缺省状态是extern的.如果一个函数要改变为只在文件内可见,加static。
5)include包含问题:虽然申明和类型定义可以重复,不过推荐使用条件编译。
#ifndef _FILENAME_H,
#define _FILENAME_H
……
#endif
实践总结:
先看最简单的程序:hello world
-
1 /*test1.c*/
-
2 main()
-
3 {
-
4 printf("Hello World!\n");
-
5 }
注意,test1中并没有.h文件,编译可以顺利通过。把程序做下改动,下面这个:
-
1 /*test2.c*/
-
2 prtstr()
-
3 {
-
4 printf("Hello World!\n");
-
5 }
-
6 main()
-
7 {
-
8 prtstr();
-
9 }
test2.c中还是没有.h文件,编译仍可以顺利通过。再把程序改动下:
-
1 /*test3.c*/
-
2 main()
-
3 {
-
4 prtstr();
-
5 }
-
6
-
7 prtstr()
-
8 {
-
9 printf("Hello World!\n");
-
10 }
test3.c中仍然没有.h文件,编译失败→_→。难道函数的位置影响编译的过程?现在我们来熟悉一下C语言中的概念:作用域。
我们在这里只讲述与.h文件相关的顶层作用域, 顶层作用域就是从声明点延伸到源程序文本结束, 就prtstr()这个函数来说,他没有单独的声明,只有定义,那么就从他定义的行开始,到文件结束, 也就是说,在test2.c的main()函数的引用点上,已经是他的作用域。 test3.c的main()函数的引用点上,还不是他的作用域,所以会编译出错. 这种情况怎么办呢? 有两种方法 ,一个就是让我们回到test2.c, 顺序对我们来说没什么, 谁先谁后不一样呢,只要能编译通过,程序能运行, 就让main()文件总是放到最后吧。那就让我们来看另一个例程,让我们看看这个方法是不是在任何时候都会起作用.
-
/*test4.c*/
-
2 play2()
-
3 {
-
4 play1();
-
5 }
-
6
-
7 play1()
-
8 {
-
9 play2();
-
10 }
-
11
-
12 main()
-
13 {
-
14 play1();
-
15 }
这就是经常用到的一种算法, 函数嵌套。play1 和play2 这两个函数哪个放到前面呢?这时就需要我们来使用第二种方法,使用声明.
-
1 /*test5.c*/
-
2 play1();
-
3 play2();
-
4
-
5 play2()
-
6 {
-
7 play1();
-
8 }
-
9 play1()
-
10 {
-
11 play2();
-
12 }
-
13 main()
-
14 {
-
15 play1();
-
16 }
一个大型的软件项目,可能有几千个,上万个 play, 而不只是 play1,play2这么简单, 这样就可能有 N 个类似 play1(); play2(); 这样的声明, 这个时候就需要我们想办法把这样的 play1(); play2(); 另行管理, 而不是把他放在.c文件中, 于是.h 文件出现了.
-
1 /*test.h */
-
2 play1();
-
3 play2();
-
4 /* test6.C */
-
5 #include “test.h”
-
6 play2()
-
7 {
-
8 play1();
-
9 }
-
10 play1();
-
11 {
-
12 play2();
-
13 }
-
14 main()
-
15 {
-
16 play1();
-
17 }
上面是.h文件的最基本的功能。
最新文章
- php在5.5.0默认提供了Zend OPcache
- NFS 文件系统
- 【笔记】ztree的使用
- yii2批量添加的问题
- Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead
- .NET实现高效过滤敏感查找树算法(分词算法):
- Android 退出app,后台推送的服务也停止了,怎么可以做到不停止后台服务呢?
- cotex_m3内核提供的ITM串口打印调试
- POI 读取Excel文档中的数据——兼容Excel2003和Excel2007
- 浮动层固定兼容IE6 position:fixed的最佳解决方案
- Java面试题之六
- MySQL存储引擎差异化实验
- (转载)Google的PageRank算法
- 宏WINAPI和几种调用约定
- js调取本地可执行文件exe
- Redis搭建多台哨兵
- app后端设计(5)-- 表情的处理
- 如何用ps简单快速扣头发丝
- notepad++安装nppFTP
- SLAM入门之视觉里程计(3):两视图对极约束 基础矩阵
热门文章
- 计算两个String 类型的时间相关几个月
- android 闹钟提醒并且在锁屏下弹出Dialog对话框并播放铃声和震动
- 支持10W高并发请求的IIS Web服务器常用设置
- swiper轮播控件配置项
- 【iOS开发系列】颜色渐变
- HDU 5071 模拟
- 硬件——STM32 , 软件框架
- ssh远程执行命令并自动退出
- jmeter--错误之Not able to find Java executable or version. Please check your Java installation. errorlevel=2
- linux中关闭程序或进程