在C语言和C++中,每个变量都有一个存储类(storage class),它决定着程序将把变量的值存储在计算机上的什么地方,如何存储,以及变量应该有着怎样的作用域与生命期。
存储类主要分为如下四个:auto、static、extern、register,现一一说明。
(1)auto(自动):
auto类是指定于在{ 和 }两个大括号之间所限定的作用域内部的局部变量的默认存储类,因为是默认的,所以你不会经常看到这个关键字,但它却是阴魂不散的。
auto变量存储在栈这个临时内存里并有着最小的作用域,当程序执行到语句块或函数末尾的大括号时,它们将被系统回收(栈回收),不复存在。例如:
{
auto int x;
int y;
}
x 和 y 都是auto存储类,只是 auto 一般都是省略的。
(2)static:
static 是全局变量的默认存储类,即全局变量不加 static 关键字默认也是 static 存储类。但是,加上 static 关键字会改变全局变量可见性,也就是说,加上 static 的全局变量在本编译单元(编译单元即为源文件)内部是可见的,其他编译单元却不可访问该全局变量。
static 也可以用来修饰局部变量,即为静态局部变量。static 变量在程序的生命期内将一直保持它的值而不会消亡,因为它们是存储在全局区(或叫静态区),生命期为从申请到程序退出。
例如:
int a;
static int b;
void fun()
{
static int c = 1;
}
int main()
{
......
return 0;
}
a 和 b 两个全局变量都是默认的static 存储类,局部变量 c 也是 static 存储类。
(3)extern:
extern 存储类在有多个翻译单元时显得非常重要。extern 用来把另一个翻译单元里的某个变量声明为本编译单元里的一个同名全局变量。extern 置于变量或函数前,以表示变量或函数已经定义在别的编译单元中,提示编译器遇到此变量或函数时,在其他编译单元中寻找其定义。
注意,编译器不会为 extern 变量分配内存,因为在其他地方已经为它分配过内存,而且不能在此处初始化。
例如:
// test1.cpp
extern int a;
int main()
{
}
// test2.cpp
int a;
void fun()
{
}
对于test1.cpp 和 test2.cpp 两个源文件,test1.cpp 中通过 extern 可以使用定义在 test2.cpp 中的变量 a。
(4)register:
register 存储类要求编译器把一个变量存储在CPU的寄存器里,register变量存储速度最快,因此可以快速访问。register变量的字节长度不应该超过寄存器的长度,也不要用取地址操作符(&)去获得此变量的内存地址。虽然 register 变量存储在寄存器里,但却有着与 auto 变量相同的作用域。
例如:
{
register int a;
}
变量 a 即为 register 存储类。