C语言头文件的使用

C语言的存储类说明符有以下几个,我来列表说明一下

说明符                     用法

Auto              只在块内变量声明中被允许,表示变量具有本地生存期.

Extern                       出现在顶层或块的外部变量函数与变量声明中,表示声明的对象

具有静态生存期,连接程序知道其名字.

Static             可以放在函数与变量声明中.在函数定义时,其只用于指定函数

                               名,而不将函数导出到连接程序.在函数声明中,表示其后面会有

定义声明的函数,存储类为static.在数据声明中,总是表示定义

的声明不导出到连接程序.

C99中规定,所有顶层的默认存储类标志符都是extern .

那么我们如何来区分哪个头文件中的声明在其对应的.c文件中有定义,而哪个又没有呢?这也许不是必须的,因为无论在哪个文件中定义,聪明的连接程序都会义无返顾的帮我们找到,并导出到连接程序,但我觉得他确实必要的.因为我们需要知道这个函数的具体内容是什么,有什么功能,有了新需求后我也许要修改他, 我需要在短时间内能找到这个函数的定义,那么我来介绍一下在C语言中一个人为的规范:

在.h文件中声明的函数,如果在其对应的.c文件中有定义,那么我们在声明这个函数时,不使用extern修饰符,如果反之,则必须显示使用extern修饰符.

在大型项目中,对全局变量的使用不可避免,比如,在first.c中需要使用一个全局变量G_test,那么我们可以在first.h中,定义TPYE G_test.与对函数的使用类似,在second.c中我们的开发人员发现他也需要使用这个全局变量,而且要与first.c中一样的那个,如何处理?对,我们可以仿照函数中的处理方法,在second.h中再次声明TPYE G_test,根据extern的用法,以及c语言中默认的存储类型,在两个头文件中声明的TPYE G_test,其实其存储类型都是extern,也就是说不必我们操心,连接程序会帮助我们处理一切.但我们又如何区分全局变量哪个是定义声明,哪个是引用声明呢?这个比函数要复杂一些,一般在C语言中有如下几种模型来区分:

1 初始化语句模型

顶层声明中,存在初始化语句是,表示这个声明是定义声明,其他声明是引用声明。C语言的所有文件之中,只能有一个定义声明。

按照这个模型,我们可以在first.h中定义如下TPYE G_test=1;那么就确定在first中的是定义声明,在其他的所有声明都是引用声明。

2 省略存储类型说明

在这个模型中,所有引用声明要显示的包括存储类extern,而每个外部变量的唯一定义声明中省略存储类说明符。

另外:

H文件和C文件怎么用呢?一般来说,H文件中是declare(声明),C文件中是define(定义)。因为C文件要编译成库文件(Windows下 是.obj/.lib,UNIX下是.o/.a),如果别人要使用你的函数,那么就要引用你的H文件,所以,H文件中一般是变量、宏定义、枚举、结构和函 数接口的声明,就像一个接口说明文件一样。而C文件则是实现细节。  
H文件和C文件最大的用处就是声明和实现分开。这个特性应该是公认的了,但我仍然看到有些人喜欢把函数写在H文件中,这种习惯很不好。(如果是C++话, 对于其模板函数,在VC中只有把实现和声明都写在一个文件中,因为VC不支持export关键字)。而且,如果在H文件中写上函数的实现,你还得在 makefile中把头文件的依赖关系也加上去,这个就会让你的makefile很不规范。  
最后,有一个最需要注意的地方就是:带初始化的全局变量不要放在H文件中!  
例如有一个处理错误信息的结构:  
char*   errmsg[]   =   {  
“No   error “,          
“Open   file   error “,      
“Failed   in   sending/receiving   a   message “,   
“Bad   arguments “,   
“Memeroy   is   not   enough “,  
“Service   is   down;   try   later “,  
“Unknow   information “,  
“A   socket   operation   has   failed “,  
“Permission   denied “,  
“Bad   configuration   file   format “,   
“Communication   time   out “,  
……  
……  
};  

请不要把这个东西放在头文件中,因为如果你的这个头文件被5个函数库(.lib或是.a)所用到,于是他就被链接在这5个.lib或.a中,而如果你的一 个程序用到了这5个函数库中的函数,并且这些函数都用到了这个出错信息数组。那么这份信息将有5个副本存在于你的执行文件中。如果你的这个errmsg很 大的话,而且你用到的函数库更多的话,你的执行文件也会变得很大。  
正确的写法应该把它写到C文件中,然后在各个需要用到errmsg的C文件头上加上   extern   char*  errmsg[];   的外部声明,让编译器在链接时才去管他,这样一来,就只会有一个errmsg存在于执行文件中,而且,这样做很利于封装。  
我曾遇到过的最疯狂的事,就是在我的目标文件中,这个errmsg一共有112个副本,执行文件有8M左右。当我把errmsg放到C文件中,并为一千多 个C文件加上了extern的声明后,所有的函数库文件尺寸都下降了20%左右,而我的执行文件只有5M了。一下子少了3M啊。

原文http://blog.csdn.net/janders/archive/2006/02/27/611081.aspx

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值