第4章 变量的存储类型
4.1 概述
C语言中的变量具有两种属性:根据变量所持有数据的性质不同而分为各种数据类型;根据变量的存储方式不同而分为各种存储类型.变量的数据类型决定了该变量所占内存单元的大小及形式;变量的存储类型规定了该变量所在的存储区域,因而规定了该变量作用时间的长短,即寿命的长短,这种性质又称为"存在性".变量在程序中说明的位置决定了该变量的作用域,即在什么范围内可以引用该变量,"可引用"又称为"可见",所以这种性质又称为"可见性".
计算机的内存和CPU中的寄存器都可以存放数据,变量究竟存放在何处则由存储类来决定.存储类型用来说明变量的作用域,生存期,可见性和存储方式.下面解释几个概念:
1 作用域:
是该变量在其上有定义的程序部分,通俗的说,即该变量起作用的某个程序区域。
2 变量的生存期:
是指它从产生到消亡的存在时间,即变量从定义开始到它所占有的存储空间被系统收回为止的这段时间。
3 变量的可见性的含义:
在某个程序区域,可以对变量进行访问(或称存取)操作,我们则称该变量在该区域为可见的,否则为不可见的。
再引入几个概念:
4 全局变量和局部变量
在一个函数内部或复合语句内部定义的变量叫内部变量,又称为"局部变量"。
在函数外定义的变量称为外部变量,又称为"全局变量"。
如:
int x ;
void main( )
{
int a, b;
float c;
……..
}
x 定义在函数外,是全局int 型变量
a,b定义在main()函数内是局部int 型变量
c 定义在main()函数内是局部float 型变量
6 动态存储变量和静态存储变量。
在程序运行期间,所有的变量均需占有内存,有的是临时占用内存,有的是整个程序运行过程中从头到尾占用内存。对于在程序运行期间根据需要进行临时性动态分配存储空间的变量称为"动态存储变量",对于在程序运行期间永久性占用内存的变量称为"静态存储变量".
一个正在运行的程序可将其使用内存的情况分为如下三类(如下图):
程序代码区: 程序的指令代码存放在程序代码区。
静态存储区: 静态存储变量存放区,包括全局变量。
动态存储区: 存放局部自动变量,函数的形参以及函数调用时的现场保护和返回地址等。
图4-1 内存分配情况
变量定义的一般形式为:
<存储类型> 数据类型 变量名表;
存储类型包括:
auto 自动型
register 寄存器型
extern 外部参照型
static 静态型
4.2 自动型变量[auto]
自动变量用关键字auto作存储类型声明
如
void main
{
auto int x, y;
auto float z;
……..
}
在主函数内定义了自动型int变量x,y和自动型float 变量z,在函数内或复合语句中定义自动型变量时auto可缺省,所以上例可以简写为:
void main
{
int x, y;
float z;
……..
}
前面章节所定义的变量用的就是这种简化形式, 所以前面章节所用变量都是auto型变量,一般情况下auto都缺省。
下面再看一个例子
if (x!=y)
{
int i ;
for (i = 0 ; i < 10 ; i++)
{
int j ;
……
}
}
在条件判断后的那个复合语句中定义了一个自动型int变量i,在for循环后的那个复合语句中定义了一个自动型int变量 j,虽然我们不提倡这种说明变量的方式,但C++可以这样定义.
2. 作用域及寿命:
由于自动型变量只能作内部变量,所以自动变量只在定义它的函数或复合语句内有效,即"局部可见"。
.变量的作用域是指该程序中可以使用该变量名字的范围。对于在函数开头声明的自动变量来说,其作用域是声明该变量的函数。不同函数中声明的具有相同名字的各个局部变量之间没有任何关系。函数的参数也是这样的,实际上可以将它看作是局部变量。
例4.1
#include <stdio.h>
void main( )
{
int x=5; //auto缺省……….(1)
printf("x=%d\t",x);
if(x>0)
{
int x=10; //………………(2)
printf("x=%d\t",x);
}
printf("x=%d\n",x+2);
}
运行结果:
x=5 x=10 x=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下面的例子说明了自动变量的特性。
#include<stdio.h>
void func( );
void func( )
{
auto int a = 0;
printf(" a of func( ) = %d\n",++a);
}
void main( )
{
int a = 10 ;
func( ); // 调用func( )函数
printf(" a of main( ) = %d\n",++a);
func( ); // 调用func( )函数
func( ); // 调用func( )函数
}
该程序的输出结果为:
a of func( )=1
a of main( )=11
a of func( )=1
a of func( )=1
当第一次调用func( )函数时,系统首先在动态存储区为func( )函数的自动变量a分配内存空间,并将初值0存放在这一空间内,接着用printf( )把自动变量a自增1后再输出显示值1,随后遇到右大括号就离开它的作用域,这时func( )函数内的自动变量的内存将释放,该变量将不存在(即寿命到), 然后返回到主函数的下一条语句。它又是一条printf( )调用语句,把主函数内的同名自动变量a自增1后再输出显示,其值为11, 接着,第2次调用func( )函数,系统再
次为func( )函数内的自动变量a分配内存空间,并初始化为0重复执行上述过程。
例4.3下面的程序说明自动变量的初始化和作用域
程序如下:
#include<stdio.h>
int n;
void show( );
void show( )
{
auto int i=3;
n++;
i++;
printf("input the value: n=%d i=%d\n", n, i);
{
auto int i=10;
i++;
printf("now the value i=%d \n",i);
}
printf("then the value i=%d\n",i);
}
void main( )
{
auto int i;
auto int n=1;
printf("at first n=%d\n",n);
for(i=1 ; i<3 ; i++)
{
show( );
}
printf("at last n=%d",n);
}
程序运行结果:
at first n=1
input the value: n=1 i=4
now the value i=11
then the value i=4
input the value: n=2 i=4
now the value i=11
then the value i=4
at last n=1
分析:
show函数的定义在主函数之前,所以不需要函数说明。
在函数外定义的变量n是全局变量初值为0,其寿命和作用域是全局的,在main()函数内定义的变量n是局部变量初值为1,其作用域是在其所在的大括号对内,在其范围内定义的变量n与全局变量n重名,根据标准中的就近原则规定,在main()函数中出现的n就是局部变量n。
在show()函数中的变量n是全局变量,其值被加1后存入n,故第一次调用show()时n的值为1,而第二次调用时n的值再被加1,故n的值为2;float型而对变量i,由于是局部auto型变量,故两次调用时i的值是一致的。
在show函数体的复合语句中,分别有一个自动变量i,它们虽然同名,但是是两个不同的变量。外层的i初始化为3,而内层初始化为10。内层的i只是在复合语句内有效,对外层的i值没有影响。
主函数main()在执行for循环语句时,两次调用了show()函数。
4.3 寄存器型变量[register]
1. 定义
在函数内或复合语句内定义,例如:
void main( )
{
register int i;
for (i=0 ;i=<100 ;i++)
{
}
}
寄存器型变量存储在CPU的通用寄存器中,因为数据在寄存器中操作比在内存中快得多,因此通常把程序中使用频率最高的少数几个变量定义为register型,目的是提高运行速度,从而节省了大量的时间。大大加快了程序的运行速度。但并不是用户定义的寄存器型变量都被放入CPU寄存器中,能否真正把它们放入CPU寄存器中是由编译系统根据具体情况做具体处理的。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论