首页 理论教育C语言存储类型:变量存储类型解析

C语言存储类型:变量存储类型解析

【摘要】:变量的生存期取决于它的存储类型。所谓“存储类型”,是指系统为变量分配的具有某种特性的存储区域。生存期表示了变量存在的时间。一个变量究竟属于哪一种存储方式,并不能仅从其作用域来判断,还应有明确的存储类型说明。在C语言中,函数内部凡未说明存储类型的变量均视为自动变量。静态局部变量始终存在着,也就是说它的生存期为整个源程序生存期。静态局部变量的使用举例。

变量的作用域来看,变量可分为“局部变量”和“全局变量”。局部变量定义在函数内部,函数调用时局部变量被临时创建,函数执行完毕,局部变量自动撤销。全局变量定义在整个程序空间,在程序运行初期被创建,整个程序执行完后才会消失。所以任何一个变量都有一个“创建”“存在”和“消亡”的过程。换句话说,变量有“寿命”或“生存期”。本节从变量的生存期这个角度来认识变量。

变量的生存期取决于它的存储类型。所谓“存储类型”,是指系统为变量分配的具有某种特性的存储区域。存储区域一般分为两种,即静态存储区和动态存储区。存放在静态存储区的变量在程序运行初期被创建,它们的寿命与程序同步;存放在动态存储区的变量是临时的,在程序运行期间随时会被撤销。这样,从变量的存储类型,就可以知道它的作用域和生存期。

(1)静态存储变量通常是在变量定义时就分定存储单元并一直保持不变,直至整个程序结束。

(2)动态存储变量是在程序执行过程中,使用它时才分配存储单元,使用完毕立即释放。典型的例子是函数的形式参数,在函数定义时并不分配存储单元,只是在函数被调用时,才予以分配,调用函数完毕立即释放。如果一个函数被多次调用,则多次分配、释放形参变量的存储单元。

从以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。这种由于变量存储方式不同而产生的特性称为变量的生存期。生存期表示了变量存在的时间。生存期和作用域是从时间和空间两个不同的角度来描述变量的特性,这两者既有联系,又有区别。一个变量究竟属于哪一种存储方式,并不能仅从其作用域来判断,还应有明确的存储类型说明。

概括地讲,变量按存储区域的不同分为以下4 种类别。

auto:动态变量。

register:寄存器变量。

extern:外部变量。

stati:静态变量。

自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式。

在介绍了变量的存储类型之后,可以知道对一个变量的说明不仅应说明其数据类型,还应说明其存储类型。因此,变量说明的完整格式应为:

例如:

下面分别介绍以上四种存储类型:

1.自动变量auto

在函数中定义的变量实际上都是自动变量,也是C语言程序中广泛使用的一种类型。在C语言中,函数内部凡未说明存储类型的变量均视为自动变量。也就是说,自动变量可缺省说明符auto。自动变量定义在函数中,当函数调用时被临时创建动态存储区,函数执行完毕,自动撤销。声明自动变量的格式:

例如:

等价于:

自动变量特点:

(1)自动变量的作用域仅限于定义该变量的个体内。在函数中定义的自动变量,只在该函数内有效。在复合语句中定义的自动变量只在该复合语句中有效。

(2)自动变量属于动态存储方式,只有在使用时才分配存储单元,开始它的生存期。函数调用结束,释放存储单元,生存期结束。因此函数调用结束,自动变量的值不能保留。在复合语句中定义的自动变量,在退出复合语句后也不能再使用。

(3)自动变量的作用域和生存期都局限于定义它的个体内 (函数或复合语句内),因此不同的个体中允许使用同名的变量,即使在函数内定义的自动变量也可与该函数内部的复合语句中定义的自动变量同名。

(4)对构造类型自动变量,譬如数组等,不能初始化赋值

2.外部变量extern

在前面介绍全局变量时已介绍过外部变量。这里仅补充说明外部变量的特点。

(1)外部变量和全局变量是对同一类变量的两种不同的提法。全局变量是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。

(2)当一个源程序由若干个源文件组成时,在一个源文件中定义的外部变量在其他的源文件中也有效。例如,有一个源程序由源文件f1.c 和f2.c 组成:(www.chuimin.cn)

在f1.c 和f2.c 两个文件中都要使用a,b,c 三个变量。在f1.c 文件中把a,b,c 都定义为外部变量。在f2.c 文件中用extern 把三个变量说明为外部变量,表示这些变量已在其他文件中定义,编译系统不再为他们分配内存空间。对构造类型的外部变量,如数组等可以在说明时初始化赋值,若不赋初值,则系统默认为0。

3.静态变量static

静态变量属于静态存储方式,但是静态存储方式的变量不一定就是静态变量,例如外部变量虽然属于静态存储方式,但不一定是静态变量,必须由static 说明后才能成为静态外部变量,或称静态全局变量。

自动变量属于动态存储方式,但是也可以用static 定义为静态自动变量,或称静态局部变量,从而成为静态存储方式。因此一个变量可由static 再说明,改变其原有的存储方式。

(1)静态局部变量。

在局部变量的说明前加上static 说明符,就构成静态局部变量。例如:

静态局部变量属于静态存储方式,具有以下特点:

① 静态局部变量在函数内定义,但不像自动变量。静态局部变量始终存在着,也就是说它的生存期为整个源程序生存期。

② 静态局部变量的生存期虽然为整个源程序的生存期,但是作用域仍与自动变量相同,即只能在定义该变量的函数内使用。退出该函数后,不能使用它。

③ 允许对构造类型静态局部变量赋初值。在数组一章,介绍数组初始化时已经说明,若未赋以初值,系统自动赋以0 值。

④ 对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋以0 值。

根据静态局部变量的特点,可以看出它是一种生存期为整个源程序生存期的变量。虽然离开定义它的函数后不能使用,但是再次调用定义它的函数时又可继续使用,而且保存了上次被调用后留下的值。因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑静态局部变量。

【例5.16】静态局部变量的使用举例。

程序运行结果如图5.14 所示。

图5.14 程序运行结果

在例5.16 中,在函数main()和函数func()中都有变量m,但是它们占用不同的内存单元,互相之间没有联系。在函数func()中,变量m 和j 均是静态变量,其初值在编译时赋予,它们在运行期间占有固定的存储单元并保留最后一次运算的值。在第一次调用后函数 main()中k=4,m=1,函数func()中的m=8, j=3 之后再调用时,经运算函数func() j=3+8+1=12;m=12+4+1=17,因此两次返回的m 值分别为8 和17。

(2)静态全局变量。

全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制其作用域,即只在定义该变量的源文件内有效,在同一源程序的其他源文件中不能使用。由于静态全局变量的作用域局限于一个源文件,只能为该源文件内的函数共用,因此可以避免在其他源文件中引起错误。

可以看出,把局部变量改变为静态变量后改变了它的存储方式,即改变了它的生存期。把全局变量改变为静态变量后改变了它的作用域,限制了它的使用范围。因此,static 说明符在不同的地方所起的作用是不同的。

4.寄存器变量register

上述变量存放在存储器中,当对一个变量频繁读写时,将花费大量的存取时间。为此,C语言提供了另一种变量,即寄存器变量。这种变量存储在CPU 的寄存器中,使用时不需要访问内存,可提高效率。寄存器变量的说明符是register。

【例5.17】 计算s=x1+x2+x3+…+xn,x 和n 由终端输入。

程序运行结果如图5.15 所示。

图5.15 程序运行结果

说明:只有局部自动变量和形式参数才可以定义为寄存器变量。因为寄存器变量属于动态存储方式。凡是采用静态存储方式的量不能定义为寄存器变量。