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