变量的存储类别
动态存储方式和静态存储方式
作用域是从空间角度分析的变量属性,而从变量值存在的时间角度来分析的变量属性称为存储期(strage duration),也叫生命期。
存储期分为 动态存储期(dynamic) 和 静态存储期(static)。 由变量的动态存储方式 和 静态存储方式决定。
动态存储方式:程序运行期间,系统对变量动态地分配存储空间。
静态存储方式:程序运行期间,系统对变量分配固定的存储空间。
程序中用的数据都放在存储区。
动态存储区:函数形式参数、自动变量、函数调用时的返回地址和信息
函数调用时,系统给它们分配动态存储空间,函数调用结束后就释放空间。在程序执行期间,它们如果被调用多次,那每次分配到的存储空间地址是动态改变的。
静态存储区:静态局部变量、静态外部变量、全局(外部)变量。
程序开始执行时,给全局变量分配存储单元,执行完毕才释放空间。在程序执行期间,它们一直占据着固定不变的存储单元。
2 存储类别
在C++中变量除了有数据类型的属性之外,还有存储类别(storage class) 的属性。存储类别指的是数据在内存中存储的方法。存储方法分为静态存储和动态存储两大类。具体包含4种:自动的(auto)、静态的(static)、寄存器的(register)和外部的(extern)。根据变量的存储类别,可以知道变量的作用域和存储期。
2.1 自动变量
函数中的局部变量,如果不用关键字static加以声明,编译系统对它们是动态地分配存储空间的。函数的形参和在函数中定义的变量(包括在复合语句中定义的变量)都属此类。
在调用该函数时,系统给形参和函数中定义的变量分配存储空间,数据存储在动态存储区中。在函数调用结束时就自动释放这些空间。如果是在复合语句中定义的变量,则在变量定义时分配存储空间,在复合语句结束时自动释放空间。因此这类局部变量称为自动变量(autovariable)。自动变量用关键字auto作存储类别的声明。(auto和变量类型的顺序任意,也可以省略,默认动态存储方式)。
2.2 static 声明静态局部变量
原本局部变量即自动变量在函数调用结束后,占用的存储单元会立即被释放。如果想要保留,则在变量声明前面加上static,指定为静态存储变量。此时存储区变为静态存储区,程序运行期间一直占着固定的空间。
自动变量 vs 静态局部变量
- 自动变量为动态存储,静态局部变量为静态存储;
- 静态变量只在编译阶段赋值一次,此后不再赋值,保留着上次函数调用的结果; 动态变量,每次函数调用时都赋一次初值。
- 若定义变量时没有赋初值。对于静态局部变量来说,编译阶段自动赋值为 0 (数值型)或 空字符(字符型)。而自动变量的值不确定。
- 虽然静态局部变量的函数调用结束后仍然存在,但终归是局部的,其他函数是不能引用它的,不可见!
使用
1.需要使用上一次函数调用结束的值;2. 该变量只被引用而不改变值。
但不建议使用,长期占用内存,且可读性差。
2.3 register 声明寄存器变量
一般情况下,变量的值是存放在内存中的。当程序中用到哪一个
变量的值时。由控制器发出指令将内存中该变量的值送到CPU中
的运算器。经过运算器进行运算,如果需要存数,再从运算器将
数据送到内存存放。
若有些变量使用频繁,则存取变量就会花很多时间。为提高执行效率,C++允许将局部变量的值放在CPU中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。这种变量叫做寄存器变量,用关键字register作声明。但只是建议性的,因为系统会自己识别使用频繁的变量,自动存放到寄存器中。
2.4 extern 声明外部变量
全局变量(外部变量)是在函数的外部定义的,它的作用域为从变量的定义处开始,到本程序文件的末尾。用extern来声明全局变量,以扩展全局变量的作用域。注意是声明已定义的外部变量,而不能同时用来定义变量。
- 在一个文件内声明全局变量
如果外部变量不在文件的开头定义,此处用关键字extern对该变量作外部变量声明,表示该变量是一个将在下面定义的全局变量。
作用域从定义处扩展至声明处。从声明处起,可合法地引用该全局变量,这种声明称为提前引用声明。
- 在多文件的程序中声明外部变量
如果一个程序包含多个文件,在多个文件中都要用到同一个外部变量。extern声明后,编译系统先在本文件中找这个外部变量,如果有则将其作用域扩展到本行开始,如果没有则在程序连接时从其他文件中找,把在另一文件中定义的外部变量的作用域扩展到本文件,在本文件中可以合法地引用该外部变量。
2.5 static 声明静态外部变量
用static声明外部变量,让其只限于被本文件引用,而不能被其他文件引用。 独立设计模块时,已知其他文件不需要用本文件的外部变量,就可以static声明,以免误用且使用相同的变量名互不干扰你。为模块化和通用性提供了方便。