首页 理论教育 C语言程序设计-变量存储方式和生存期

C语言程序设计-变量存储方式和生存期

时间:2023-10-20 理论教育 版权反馈
【摘要】:图8.5用户使用的存储空间程序区用来存放程序代码,动态存储区和静态存储区用来存放数据。局部变量采用动态存储方式,在函数调用时在动态存储区给局部变量分配空间,函数调用结束释放空间。自动变量用关键字auto 作存储类别的声明。静态局部变量始终存在着,也就是说它的生存期为整个源程序。静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。

C语言程序设计-变量存储方式和生存期

内存中供用户使用的存储空间可分为程序区、动态存储区和静态存储区,如图8.5 所示。

图8.5 用户使用的存储空间

程序区用来存放程序代码,动态存储区和静态存储区用来存放数据。静态存储区即全局数据区,用来存放程序的全局数据和静态数据。动态存储区又分为堆区和栈区,堆区用来存放程序中的动态数据;栈区用来存放程序的局部数据,即每个函数中的数据。

动态存储和静态存储是C语言中数据存储的两种方式。动态存储是指存储数据的存储单元可在程序运行的不同时间分配给不同的数据;静态存储是指存储单元在程序运行的整个过程中固定地分配给某些数据,在程序运行期间不释放。

全局变量采用静态存储方式,在程序开始执行时在静态存储区给全局变量分配空间,在程序运行过程中它们占据固定的存储单元,程序执行完毕才释放空间。

局部变量采用动态存储方式,在函数调用时在动态存储区给局部变量分配空间,函数调用结束释放空间。

每一个变量和函数即有两个属性,即数据类型和数据的存储类别。其中数据类型在前面的章节已经介绍过,如整型、实型、字符型等。本节主要讲解数据的存储类型。C语言的数据有四种存储类型,分别为:auto、extern、static、register。

1.auto——声明自动变量

在函数内部定义的变量称为局部变量,局部变量又称为自动变量。在调用函数时,系统给自动变量分配空间,函数调用结束后自动释放这些空间。自动变量用关键字auto 作存储类别的声明。如:

autofloat p=12.3;

关键字auto 可以省略,此时默认为"自动存储类别",属于动态存储方式,函数中的变量大多属于自动变量。

【例8.13】自动局部变量的使用。

程序代码:

运行结果:

程序讲解:

在上面的程序中,定义了两个同名自动变量i,它们分别位于不同的函数中,分配不同的存储单元,因而互不干扰。在main 函数中调用fun 函数三次,但因为变量i 是自动变量,当fun 函数调用时,为i 分配存储空间,函数调用结束后释放存储空间。每次调用都重新为其分配新的存储空间,且每次都初始化为0。

2.static——声明静态变量

静态变量分为静态局部变量和静态全局变量。

静态局部变量是定义在函数内部的。静态局部变量定义时前面要加static 关键字来标识,静态局部变量在第一次函数被调用时创造并初始化,但在函数调用结束时,该变量仍在内存中存在,并且保持其值等待函数下一次被调用。

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

程序代码:

运行结果:

程序讲解:

在函数fun 中定义的局部自动变量a 和静态局部变量b。在main 函数中,调用了3 次fun函数,每次调用fun 函数都会为局部自动变量a 分配空间并且重新赋值,每次函数调用a 的初值都为1。而对于静态局部变量b 来说,在程序运行时为其分配内存空间,并赋初值为2,第一次函数调用时,对b 进行自增操作,b 的值为3;当第一次调用结束后,b 的值为3 并保存在内存中;第二次函数调用时,对b 进行自增操作,b 的值在3 的基础上修改为4,当第二次调用结束后,b 的值为4 并保存在内存中;第三次函数调用时,对b 进行自增操作,b 的值在

4 的基础上修改为5,当第三次调用结束后,b 的值为5 并保存在内存中。(www.xing528.com)

注意局部自动变量和静态局部变量的区别:

(1)静态局部变量在函数内定义,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序

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

(3)对基本类型的静态局部变量若在定义时未赋以初值,则系统自动赋予0 值。而对自动变量不赋初值,则其值是不定的。

思考一下:当定义静态局部变量b 时,如果未赋值,程序的运行结果是什么?

如果在程序设计中希望某些全局变量只限于本文件使用,而不能被其他文件使用,可以在定义全局变量时加上关键字static,这种加上static 只能用于本文件的全局变量,称为静态全局变量。

3.register——声明寄存器变量

寄存器是CPU里面的一块能够快速访问的地方,比内存还快。register 只是"请求"编译器把数据存储到寄存器中,并不能保证这个数据一定在寄存器中,由于某些原因(比如寄存器不够用或编译器认为没必要)数据可能不会被存储到寄存器中。另外,寄存器没有地址,所以对register变量取地址是不会编译通过的,即使编译器没有把它存到寄存器中。

register 只是寄存器变量,表示这个数据要保存在寄存器中,和任何运算都没有关系,比如你的变量是保存在内存还是缓存中都不重要,和程序没有多大联系,把register去掉,程序该怎么样就怎么样。用寄存器变量是为了提高程序运行速度,因为寄存器是取值和修改最快的,所以把那些需要多次使用的变量保存在寄存器中是一种提高效率的做法,和算法无关。

由于现在计算机的速度越来越快,优化的编译系统能够识别使用频繁的变量,从而自动将这些变量放在寄存器中,而不需要程序设计者指定。因此,现在实际上用register声明变量是不必要的。

4.extern——声明外部变量的作用范围

(1)在一个文件内扩展全局变量的作用域。

如果全局变量不在文件的开头定义,其有效的作用域只限于定义点到文件结束。在定义点之前的函数不能引用该外部变量。如果希望在定义点之前的函数可以引用该全局变量,则应该在引用之前用关键字extern 对该变量作"外部变量声明"。

【例8.15】全局变量声明。

程序代码:

运行结果:

程序讲解:

全局变量a 的定义在fun1 函数之后,fun1 函数不能使用全局变量a。希望fun1 函数能使用全局变量a,在程序开头对声明了全局变量,扩展了全局变量a 的作用域。

(2)将外部变量的作用域扩展到其他文件。

一个C 程序可以由多个源文件组成,如果希望在不同的源文件中使用同一个变量,也可以通过extern 进行外部变量声明。

【例8.16】扩展外部变量的作用域到其他文件。

程序代码:

运行结果:

程序讲解:

上面的程序包含了两个文件,在运行时分别对它们进行编译。变量a、b、c 在file1.c 文件中被定义为外部变量并赋值。在文件file2.c 中对变量a、b、c 做extern 声明。确定变量a、b、c 是三个已经在其他文件中定义过的外部变量,因此不必再次为它们分配存储空间,可以直接使用它们的值。通过extern 声明,使原本只能在file1.c 中使用的变量可以在file2.c 中使用,扩大了它们的作用域。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈