一个变量除了数据类型以外,还有3种属性:
以上3种属性是有联系的,程序设计者只能声明变量的存储类别,通过存储类别可以确定变量的作用域和存储期。
要注意存储类别的用法。auto, static和register 3种存储类别只能用于变量的定义语句中,如:
auto char c; //字符型自动变量,在函数内定义
static int a; //静态局部整型变量或静态外部整型变量
register int d; //整型寄存器变量,在函数内定义
extern int b; //声明一个已定义的外部整型变量
说明: extern只能用来声明已定义的外部变量,而不能用于变量的定义。只要看到extern,就可以判定这是变量声明,而不是定义变量的语句。
下面从不同角度分析它们之间的联系。
1) 从作用域角度分,有局部变量和全局变量。它们采用的存储类别如下:
2) 从变量存储期(存在的时间)来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。
3) 从变量值存放的位置。可分为:
4) 关于作用域和存储期的概念。
从前面叙述可以知道,对一个变量的性质可以从两个方面分析,一是从变量的作用域,一是从变量值存在时间的长短,即存储期。前者是从空间的角度,后者是从时间的角度。二者有联系但不是同一回事。图4.16是作用域的示意图,图4.17是存储期的示意图。
如果一个变量在某个文件或函数范围内是有效的,则称该文件或函数为该变量的作用域,在此作用域内可以引用该变量,所以又称变量在此作用域内“可见”,这种性质又称为变量的可见性,例如图4.16中变量a、b在函数f1中可见。
如果一个变量值在某一时刻是存在的,则认为这一时刻属于该变量的存储期,或称该变量在此时刻“存在”。表4.2表示各种类型变量的作用域和存在性的情况。
变量存储类别 | 函数 | 内 | 函数 | 外 |
---|---|---|---|---|
作用域(可见性〉 | 存在性 | 作用域(可见性) | 存在性 | |
自动变童和寄存器变置 | √ | √ | X | X |
静态局部变量 | √ | √ | X | √ |
静态外部变童 | √ | √ | √(只限本文件) | √ |
外部变量 | √ | √ | √ | √ |
其中“√”表示是,“X”表示否。可以看到自动变量和寄存器变量在函数内的可见性和存在性是一致的。在函数外的可见性和存在性也是一致的。静态局部变量在函数外的可见性和存在性不一致。静态外部变量和外部变量的可见性和存在性是一致的。
如果一个变量在某个文件或函数范围内是有效的,则称该文件或函数为该变量的作用域,在此作用域内可以引用该变量,所以又称变量在此作用域内“可见”,这种性质又称为变量的可见性,例如图4.16中变量a、b在函数f1中可见。
如果一个变量值在某一时刻是存在的,则认为这一时刻属于该变量的存储期,或称该变量在此时刻“存在”。书中表4.2表示各种类型变量的作用域和存在性的情况。
可以看到自动变量和寄存器变量在函数内的可见性和存在性是一致的。在函数外的可见性和存在性也是一致的。静态局部变量在函数外的可见性和存在性不一致。静态外部变量和外部变量的可见性和存在性是一致的。
5) static声明使变量采用静态存储方式,但它对局部变量和全局变量所起的作用不同。
对局部变量来说,static使变量由动态存储方式改变为静态存储方式。而对全局变量来说,它使变量局部化(局部于本文件),但仍为静态存储方式。从作用域角度看,凡有static声明的,其作用域都是局限的,或者局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)。