存储类型可以用于变量以及较小范围的函数和形式参数的说明。现在集中讨论变量的存储类型。
回顾一下以前的内容,块(block)表示函数体(花括号包括的部分)或者复合语句(可能包含声明)。在C99中,选择语句(if 和 switch)、循环语句(while、do和for)以及它们所控制的“内容”语句也被视为块,尽管本质上有一些差别。
变量的性质:
C语言程序中的每个变量都具有以下3个性质。
- 存储期限。变量的存储期限决定了为变量预留和内存被释放的时间。具有自动存储期限的变量在所属块被执行时获得内存单元,并在块终止时释放内存单元,从而会导致变量失去值。具有静态存储期限的变量在程序运行期间占有同一个的存储单元,也就允许变量无限期地保留它的值。
- 作用域。变量的作用域是指可以引用变量的那部分程序文本。变量可以有块作用域(变量从声明的地方一直到所在块的末尾都是可见的)或者文件作用域(变量从声明的地方一直到所在文件的末尾都是可见的)。
- 链接。变量的链接确定了程序的不同部分可以共享此变量的范围。具有外部链接的变量可以被程序中的几个(或许全部)文件共享。具有内部链接的变量只能属于单独一个文件,但是此文件中的函数可以共享这个变量。(如果具有相同名字的变量出现在另一个文件中,那么系统会把它作为不同的变量来处理。)无链接的变量属于单独一个函数,而且根本不能被共享。
变量的默认存储期限、作用域和链接都依赖于变量声明的位置。
- 在块(包括函数体)内部声明的变量具有自动存储期限、块作用域,并且无链接。
- 在程序的最外层(任意块外部)声明的变量具有静态存储期限、文件作用域和外部链接。
对许多变量而言,默认的存储期限、作用域和链接是符合要求的。当这些性质无法满足要求时,可以通过指定明确的存储类型(auto、static、extern、register)来改变变量的性质。
现在对已知内容进行一个总结,下面的代码段说明了变量和形式参数声明中包含或者省略存储类型的所有可能的方法。
int a; extern int b; static int c; void f( int d, register int e) { auto int g; int h; static int i; extern int j; register int k; }
下表说明了上面代码中每个变量和形式参数的性质
变量名 | 存储期限 | 作用域 | 链接 |
a | 静态 | 文件 | 外部 |
b | 静态 | 文件 | ① |
c | 静态 | 文件 | 内部 |
d | 自动 | 块 | 无 |
e | 自动 | 块 | 无 |
g | 自动 | 块 | 无 |
h | 自动 | 块 | 无 |
i | 静态 | 块 | 无 |
j | 静态 | 块 | ① |
k | 自动 | 块 | 无 |
①由于这里没有显示出变量b和j的定义,所以不可能确定它们的链接。在大多数情况下,变量会定义在另一个文件中,并且具有外部链接。
在这4种存储类型之中,最重要的是extern和static。auto没有任何效果,而现代编译器已经使register变得不如以前重要了。
参考资料:
《C程序设计语言 第二版》
《C语言程序设计现代方法 第二版》