第04章变量的存储类型_第1页
第04章变量的存储类型_第2页
第04章变量的存储类型_第3页
第04章变量的存储类型_第4页
免费预览已结束,剩余24页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、芀 第 4 章变量的存储类型蝿 4.1 概述袅 C 语言中的变量具有两种属性 : 根据变量所持有数据的性质不同而分为各种数据类型;根据变量的存储方式不同而分为各种存储类型. 变量的数据类型决定了该变量所占内存单元的大小及形式;变量的存储类型规定了该变量所在的存储区域, 因而规定了该变量作用时间的长短,即寿命的长短,这种性质又称为 存在性 . 变量在程序中说明的位置决定了该变量的作用域, 即在什么范围内可以引用该变量, 可引用 又称为 可见 ,所以这种性质又称为 可见性 .莄计算机的内存和CPU中的寄存器都可以存放数据,变量究竟存放在何处则由存储类来决定 . 存储类型用来说明变量的作用域,生存期

2、,可见性和存储方式. 下面解释几个概念:蚂1 作用域 :艿是该变量在其上有定义的程序部分,通俗的说,即该变量起作用的某个程序区域。薆 2 变量的生存期 :莅是指它从产生到消亡的存在时间,即变量从定义开始到它所占有的存储空间被系统收回为止的这段时间。螀 3 变量的可见性的含义 :蚈在某个程序区域,可以对变量进行访问 ( 或称存取 ) 操作,我们则称该变量在该区域为可见的,否则为不可见的。莆再引入几个概念:膂 4 全局变量和局部变量膃在一个函数内部或复合语句内部定义的变量叫内部变量,又称为 局部变量 。肇在函数外定义的变量称为外部变量,又称为 全局变量 。肆 如:芄 int x ;芁 void m

3、ain( )螁 袇int a, b;莅 float c;荿.膀 薇 x 定义在函数外,是全局int型变量膂 a,b 定义在 main() 函数内是局部int型变量螂 c定义在main()函数内是局部float型变量蚀芈 6 动态存储变量和静态存储变量。膄在程序运行期间,所有的变量均需占有内存,有的是临时占用内存,有的是整个程序运行过程中从头到尾占用内存。 对于在程序运行期间根据需要进行临时性动态分配存储空间的变量称为 动态存储变量 ,对于在程序运行期间永久性占用内存的变量称为 静态存储变量.袀一个正在运行的程序可将其使用内存的情况分为如下三类( 如下图 ):聿程序代码区 :程序的指令代码存放在

4、程序代码区。肈静态存储区 :静态存储变量存放区,包括全局变量。芅动态存储区 : 存放局部自动变量,函数的形参以及函数调用时的现场保护和返回地址等。芃蒈 图 4-1内存分配情况螈 变量定义的一般形式为:肃 数据类型 变量名表;莁存储类型包括:袈芅肄葿auto自动型register寄存器型extern外部参照型static静态型莇 4.2 自动型变量 auto羅自动变量用关键字auto 作存储类型声明膅如袂 void main肀 螅 auto int x, y;羃 auto float z;羀.蒀 蒆在主函数内定义了自动型 int 变量 x, y 和自动型 float 变量 z,在函数内或复合语句

5、中定义自动型变量时 auto 可缺省,所以上例可以简写为 :羄 void main莃 衿int x, y;芆float z;肅.蒁艿前面章节所定义的变量用的就是这种简化形式,所以前面章节所用变量都是auto 型变量,一般情况下auto 都缺省。羇下面再看一个例子袃 if (x!=y)袃 螈int i ;螇for (i = 0 ; i 10 ; i+)羄羂intj ;膇蒇 羆 肀在条件判断后的那个复合语句中定义了一个自动型int变量 i ,在 for循环后的那个复合语句中定义了一个自动型int变量 j ,虽然我们不提倡这种说明变量的方式,但C+可以这样定义 .袁 2.作用域及寿命:芈由于自动型变

6、量只能作内部变量,所以自动变量只在定义它的函数或复合语句内有效,即 局部可见 。螃.变量的作用域是指该程序中可以使用该变量名字的范围。 对于在函数开头声明的自动变量来说, 其作用域是声明该变量的函数。 不同函数中声明的具有相同名字的各个局部变量之间没有任何关系。函数的参数也是这样的,实际上可以将它看作是局部变量。蒂例 41芀 #include 羈 void main( )袄 薁int x=5;/auto缺省 .(1)虿 printf(x=%dt,x);蒄if(x0)袆 羃int x=10; /(2)腿printf(x=%dt,x);膅蚃 printf(x=%dn,x+2);肁 薈羅 运行结果

7、:螄 x=5x=10x=7膀第一个 printf()语句中的 x 的是 (1) 处说明的,所以 x=5;第二个 printf()语句中的x 的是 (2) 处说明的,虽然 if语句后的一对大括号,是包含在外层的大括号内,即前面一个 x 变量的内存还没释放,但C+规定当出现类似的情况时,以内层说明优先,即相当于内层说明的变量 x 是另外一个变量 x, 在其所在的大括号内如果不包括更深层次的同名变量说明,则其中所引用的 x 就是 x;所以 x=10;羈第三个 printf() 语句中的 x 的是 (1) 处说明的,因为这时 (2) 处说明的变量 x 已释放;故结果为 x=7.蚆 例 4 2 下面的例

8、子说明了自动变量的特性。螆 #include薂 void func( );蒇 void func( )蒆薃auto int a = 0;蚁printf( a of func( ) = %dn,+a);肀 膆 void main( )蚅 羃 int a = 10 ;薀func( );/调用 func( )函数膃 printf( a of main( ) = %dn,+a);蚈 func( );/调用 func( )函数莇 func( );/调用 func( )函数膅 袃 该程序的输出结果为:蝿 a of func( )=1蒆 a of main( )=11蚅 a of func( )=1蚄 a

9、of func( )=1螁当第一次调用func( )函数时,系统首先在动态存储区为func( )函数的自动变量a分配内存空间,并将初值0 存放在这一空间内,接着用printf() 把自动变量a 自增 1 后再输出显示值1,随后遇到右大括号就离开它的作用域,这时func( )函数内的自动变量的内存将释放,该变量将不存在( 即寿命到 ) ,然后返回到主函数的下一条语句。它又是一条printf( )调用语句,把主函数内的同名自动变量a 自增 1 后再输出显示,其值为11, 接着,第 2 次调用 func( ) 函数,系统再次为 func( ) 函数内的自动变量 a 分配内存空间,并初始化为 0 重复

10、执行上述过程。袈 例 4 3 下面的程序说明自动变量的初始化和作用域肄 程序如下 :莄 #include薈 int n;羇 void show( );蒃 void show( )肄 虿 auto int i=3;荿膇 n+;薁 i+;螁 printf(input the value: n=%d i=%dn, n, i);蒇 薆auto int i=10;莁 i+;薈 printf(now the value i=%d n,i);薆 肅 printf(then the value i=%dn,i);肁 薀羈 void main( )蒅 袂 auto int i;蚁 auto int n=1;肆袄

11、 printf(at first n=%dn,n);薂 for(i=1 ; i3 ; i+)蒈 荿 show( );芄 芃 printf(at last n=%d,n);蒀薇 羇肃程序运行结果:薁 at first n=1蚆蒆螃莈羈袆薄莀input the value: n=1 i=4now the value i=11then the value i=4input the value: n=2 i=4now the value i=11then the value i=4at last n=1膆分析 :芅 show 函数的定义在主函数之前,所以不需要函数说明。芄在函数外定义的变量n 是全局变

12、量初值为0,其寿命和作用域是全局的,在main() 函数内定义的变量n 是局部变量初值为1,其作用域是在其所在的大括号对内,在其范围内定义的变量n 与全局变量n 重名,根据标准中的就近原则规定,在main() 函数中出现的n 就是局部变量n。蒁在 show() 函数中的变量n 是全局变量,其值被加1 后存入n,故第一次调用show()时 n 的值为 1,而第二次调用时n 的值再被加1,故 n 的值为 2; 而对变量i ,由于是局部auto型变量,故两次调用时i 的值是一致的。葿在 show 函数体的复合语句中,分别有一个自动变量i ,它们虽然同名,但是是两个不同的变量。 外层的 i 初始化为

13、3,而内层初始化为 10。内层的 i 只是在复合语句内有效, 对外层的 i 值没有影响。蚄主函数 main()在执行for循环语句时,两次调用了show() 函数。肄 4.3寄存器型变量register艿1. 定义薇在函数内或复合语句内定义,例如:膄 void main( )蒁 莀register int i;蚅for (i=0 ;i=100 ;i+)薃芁莁 肈寄存器型变量存储在CPU 的通用寄存器中, 因为数据在寄存器中操作比在内存中快得多,因此通常把程序中使用频率最高的少数几个变量定义为register 型,目的是提高运行速度,从而节省了大量的时间。大大加快了程序的运行速度。但并不是用户定

14、义的寄存器型变量都被放入CPU 寄存器中,能否真正把它们放入CPU寄存器中是由编译系统根据具体情况做具体处理的。芇 2. 分配寄存器的条件是 :羁有空闲的寄存器;腿变量所表示的数据的长度不超过寄存器的位长;膆 3. 作用域和寿命同auto 类型,也是在定义它的函数或复合语句内有效,即 局部可见 。蚆 例 4 4 用寄存器变量提高程序执行速度。螂 #include芀 / 函数的形参也可以指定为寄存器变量,一个函数一般以拥有2 个寄存器变量为宜/蕿 #define t 10000肅 void delay1( );蒂 void delay2( );芁 void delay1( )蚇 薅 regist

15、er unsigned i=0 ;芃 for ( ; it ; i+)聿 聿羄羃 膀 void delay2( )膈 莃蚃膂unsigned i ;for (i=1 ; it ; i+)芆 肇 蒄 void main( )罿 蚈蒆unsigned int i;膄 printf(a调用 delay1( ) 第一次延时 !n);肀for ( i=0 ; i60000 ; i+)螇羆 delay1();蚀 膂printf(a第 1 次延时结束 !n调用 delay2( )第 2 次延时 !n);腿for ( i=0 ; i60000 ; i+)莅蒁 delay2();罿 芈printf(a第 2 次

16、延时结束 !n);螄 膁该程序运行结果为;羀调用 delay1( )第一次延时 !莆第 1 次延时结束 !芄调用 delay2( )第 2 次延时 !袂第 2 次延时结束 !肂由于delay1( )函数使用了寄存器,它的执行速度比不使用寄存器变量的delay2( )函数要快。螈尽管使用寄存器变量可以提高程序运行的速度,但计算机的寄存器是有限的,为确保寄存器用于最需要的地方,应将使用最频繁的变量说明为寄存器存储类型。蚃 4.4外部参照型变量extern蚂1. 定义衿 extern 型变量一般用于在程序的多个编译单位之间传送数据,在这种情况下指定为extern型的变量是在其它编译单位的源程序中定义

17、的,它的存储空间在静态数据区,在程序执行过程中长期占用空间。要访问另一个文件中定义的跨文件作用域的全局变量,必须进行 extern 说明。例如 :袇 /*file1.c*/*file2.c*/*file3.c*/莆 etern int x;extern int x;int x=0;莂 void main( )void fun1( ) void fun2( )袁 艿 x+;x += 3;printf(%d,x);螆 膃 file1.c和 file2.c中的 extern int x; 告诉编译程序X 是外部参照变量,应在本文件之外去寻找它的定义。所以上面的 x 虽在两个源文件中,但它们是同一个变

18、量。 在文件之外的 file3.c中,定义了int x=0 ,即为它们调用的变量。蚈如果外部变量不在文件的开头部分定义,其有效的作用范围只限于从定义处到文件结束。如果定义点之前的函数想引用外部变量,则应该在引用前用关键字extern,从而对该变量作外部声明,有了此声明,就可以从声明处起,合法的使用该外部变量。莇作用域及寿命 : 全局存在,全局可见;膅例 4 5 下例说明了外部变量的特性。袃#include 蝿 int n = 100;蒆 void hanshu();蚅 void hanshu(void)蚄螁n-=20 ;袈肄 int main(void)莄薈 printf(n=%dn,n);羇

19、蒃 for( ; n=60 ; )肄 虿hanshu( );荿printf(n=%dn,n);膇薁 return 0 ;螁蒇 执行结果 :薆n=100 ;莁n=80 ;薈 n=60 ;薆n=40 ;肅 n 是 int型外部变量, 定义时被显示初始化为100。进入 for语句时, n 值开始为100,每次调用 hanshu( ) 后值减少 20,直到 n 值小于 60 为止。for循环体三次调用函数hanshu( ) ,第二,第三次调用执行函数体中的赋值语句n-=20 ; 时 n 的值就是上次调用后的值。可见外部变量值的连续性。肁我们把上面的程序改一下。如果外部变量n 的定义性说明在hanshu

20、 之后,系统在该处给变量分配存储并执行初始化,由于hanshu 中的 n 值是在 n 定义之前引用的,因此必须要用 extern 对 n 做引用说明(如下面程序) ,外部变量引用说明时不分配存储, 也不初始化,但在实际编程中我们不提倡这种用法。薀羈#include蒅 extern int n;袂 void hanshu();蚁 void hanshu(void)肆 袄 n -= 20 ;薂 蒈荿 int n=100;芄 int main(void)芃蒀 printf(n=%dn,n);薇羇 for( ; n=60 ; )肃 薁 hanshu( );蚆 printf(n=%dn,n);蒆 螃 r

21、eturn 0 ;莈 羈 执行结果 :袆 n=100 ;薄 n=80 ;莀n=60 ;膆n=40 ;芅使用这样的全局变量应十分慎重,因为在执行一个文件中的函数时,可能会改变了该全局变量的值,它会影响到另一文件中的函数执行结果。芄 例 4.6用 extern声明外部变量:蒁 本程序的作用是给定b 的值,输入a 和 m,求 a*b ,和 a m 的值。葿 文件 file1.c中的内容为 :蚄 #include 肄 int a;艿 int m;薇 int power();膄 void main()蒁 莀 int b=3,c,d;蚅薃 printf(input the number a and its

22、 power m:n);芁 scanf(%d,%d,&a,&m);莁 c = a*b;肈 printf(%d*%d=%dn,a,b,c);芇 d = power();羁 printf(%d*%d=%d,a,m,d);腿 膆蚆 文件 file2.c中的内容为 :螂 extern int a;芀 extern int m;蕿肅 int power();蒂 芁 int i,y=1;蚇 for ( i=1 ; i=m ; i+)薅 芃y*=a;聿 聿 return(y);羄 羃该程序的运行结果为:膀 input the number a and its power m:膈 5,4/输入莃 5*3=15

23、/输出蚃 5*4=625膂从上面可以知道,file2.c 文件中的开头有两个extern 声明,它们声明在本文件中出现的变量 a 和 m 是已经在其它文件定义过的外部变量,本文件不必再次为它分配内存。也就是说,本来外部变量a 和 m 是定义在file1.c 中的,但用extern 扩展到 file2.c 上了,这样即使程序有 N 个源文件,在一个文件中定义了外部整型变量a,其它 N-1 个文件都可以引用。芆 4.5 静态型变量 static肇1. 定义蒄静态型变量既可以在函数或复合语句内进行,也可以在所有函数之外进行。在函数或复合语句内部定义的静态变量称为局部静态变量,在函数外定义的静态变量称

24、为全局静态变量。有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下次该函数调用时,该变量已有值,其值就是上一次函数调用结束时的值。这时就应该指定该局部变量为 静态局部变量,用关键字static 进行声明。例如:罿 static float x; /*定义全局静态变量*/蚈void main( )蒆膄肀螇羆static int y;/*定义 y 局部静态变量 */蚀局部静态变量和自动变量一样只有定义性说明,没有引用性说明,因此必须先定义后引用。外部静态变量的初始化同外部变量。局部静态变量在第一次进入该块时执行一次且仅执行一次初始化; 在有显式初始化的情况

25、下, 初值由说明符中的初值说明来确定; 在无显式初始化情况下,初值与外部变量无显式初始化时的初值相同。膂 2.作用域和寿命腿 static 类型变量都是全局寿命。莅全局 static变量 全局可见。蒁局部 static变量 局部可见。例4.7例4.8罿考察静态变量的值。芈#include 螄int a = 2;膁 int f();羀 int f()莆芄袂肂螈蚃蚂衿袇莆莂袁艿螆膃蚈莇auto int b=0;static int c=3;b+;c+;return(a+b+c) ;void main( )int i;for(i=0;i3;i+)printf(%dt,f();运行结果为 :789膅在

26、第一次调用f() 函数时, b 的初值为0,第一次调用结束时,b=1, c=4, a+b+c=7 ,由于 c 是静态局部变量,在函数调用后,它并不释放,仍保留 c=4。在第 2 次调用 f() 函数时, b 的初值为 0,而 c 的初值为 4(上次调用结束时的值 )。袃注意事项 :蝿(1).对静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。 而自动变量 ( 动态局部变量 ) 属于动态存储类别, 占动态存储空间而不占静态存储空间,函数调用结束后即释放。蒆(2).对静态局部变量只赋初值一次,以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而对

27、自动变量赋初值,每次用一次函数重新给一次初值,相当于执行一次赋值语句。蚅(3).如在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋值初值 0( 对数值型变量) 或空字符 ( 对字符变量 ) 。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。这是由于每次函数调用结束后存储单元已释放 ,下次调用时又重新另配置存储单元,而所分配的单元中的值是不确定的。蚄(4).有时在程序设计中希望某些外部变量只限于被本文件引用,而不能被其它文件引用。这时可以在定义外部变量时加一个static声明。螁 例如 : 在上文关于extern讲解中的实例,作如下改动袈 /*file1.c*/*file

28、2.c*/*file3.c*/肄 etern int x;extern int x;static int x=0 ;莄 void main( )void fun1( ) void fun2( )薈 羇 x+;x+=3;printf(%d,x);蒃 肄 file3.c中定义了全局变量 x,但是用了 static 声明,因此只能用于本文件, 虽然在file1.c 和 file2.c 中用了 extern int x; ,但都无法使用 file3.c 中的全局变量 x . 这为程序的模式化,通用性提供了方便。虿 例 4 8 下面的程序说明外部静态变量和外部变量的区别荿 文件 file1.c如下 :膇

29、#include薁 static float x;螁 float y ;蒇 float f2();薆 float f1();莁 float f1()薈 薆return(x*x);肅 肁薀 void main()羈 蒅x=500;袂y=100;蚁printf(f1=%f,f2=%fn, f1(), f2();肆袄薂 文件 file2.c如下 :蒈 extern float y;荿 float f2()芄 芃return(y*y);蒀 薇 输出 : fl=250000.000000 , f2=10000.000000羇该程序包含两个文件三个函数,函数 main 和 f1 在文件 file1.c 中

30、,函数 f2 在文件 file2.c中,变量 x 是 float 型外部静态变量。它只能在file1.c 和 main 函数中使用。变量y 是在文件file1.c 中定义的外部变量, 他可以在 file1.c 和主函数中直接使用, 也可以在 file2.c 中参照说明。肃 例 4 9 局部静态变量与自动变量的区别。莅 #include莀 void value( );膀 void value( )薇 膂 int au=0;螂 static int st=0;蚀芈 printf(au_variable=%d,st_variable=%dn,au,st);膄 au+;袀 st+;聿 肈芅 void

31、main( )芃 蒈 int i;螈肃 for(i=0;i3;i+)莁 袈value( );芅肄 葿莇程序运行结果:羅 au_variable=0, st_variable=0膅 au_variable=0, st_variable=1袂 au_variable=0, st_variable=2肁分析 :由于变量au 是局部自动变量,st 是局部静态变量,定义时二者都赋初值为0,main 函数三次调用value()函数, au 是局部自动变量,每次再调用时都要重新对au 初始化;而 st 由于是静态变量,再调用时不再执行初始化,每次值增1,注意变量au 在退出value函数时存储单元被系统收回

32、,下次进入时重新分配存储空间。螆 4.6 存储类型小结羃 1. 关于类型说明羀关键字 auto ,static ,register用于定义变量的存储类型说明,其中 auto 通常缺省。而关键字 extern 则不然,它不是用于定义变量而是用于说明某个变量,是已在本函数之外或其它源文件中定义过的外部变量,加 extern说明有 延伸外部参照型变量作用域 的作用。蒀 2. 关于变量的作用域和寿命局部Autoregister变量局部static 型可见性( 作用域)全局static 型全局变量外部参照型具有Auto“局部寿命”register存在性具有Static“全局寿命”外部参照型蒆羄 3. 关于变量的初始化莃有关变量初始化的知识,在前面有关章节已讲述过,此处只对各种存储类型变量在初始化方面的区别加以总结。衿(1)对于 atuo 型和 register型变量 :芆由于这两种变量的内存都是动态分配的,因此每次进入函数或复合语句都要重新分配内存并执行初始化。故不管何时进入函数或复

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论