### 变量的存储类型

在 C++语言中，变量通常有 4 种存储类型，分别为“extern”、“static”、“register”和“auto”。下面逐一进行介绍。

l extern 存储类型

在介绍 extern 存储类型之前，先来澄清一个概念——变量的声明和定义。变量的声明是告知编译器变量的名称和数据类型。变量的定义将为变量分配存储区域。通常情况下，变量的声明也被认为是变量的定义。但是可以使用 extern 关键字只声明而不定义变量。例如：

extern int var;

那么只声明而不定义变量有何好处呢？通常，应用程序可能包含许多文件，如果在一个文件中定义一个全局变量，可能需要在其他文件中进行访问。那么在其他文件中可以使用 extern 关键字只声明而不定义全局变量，extern 关键字将告诉编译器变量的名称和类型，而变量的定义来源于前一个文件。这样就可以在其他文件中共享全局变量了。例如，在一个文件中定义一个整形的全局变量 var。

int var = 0 ;

而在另一个文件中通过使用 extern 关键字声明全局变量 var，在该文件中就可以访问全局变量 var 了。

extern int var;

l static 存储类型

在介绍 static 存储类型之前，先来介绍一下局部变量和全局变量。变量按照作用范围的不同可以划分为局部变量和全局变量。局部变量是指在函数内定义的变量，在函数调用结束后，局部变量将消失。而全局变量是指在函数体外定义的变量，它的生命期随着程序的结束而结束。

static 存储类型主要是针对局部变量的，如果定义一个静态的局部变量，它的生命期在函数调用结束后会依然存在，在下次调用函数时，会依然保存上一次函数调用结束之后的值。并且，对于静态变量只执行一次初始化（无论函数调用多少次）。

static 存储类型表示变量在函数或文件内是“持久性”变量，通常也被称之为静态变量。静态变量分为局部静态变量和全局静态变量。当使用 static 关键字标识一个局部变量（在函数内部定义的变量）时，该变量将被分派在一个持久的存储区域，当函数调用结束时，变量并不被释放，依然保留其值。当下一次调用函数时，将应用之前的变量值。这一点类似于全局变量，但是与全局变量不同的是，局部静态变量的作用域为当前的函数，它不能被外界函数或文件访问。可以认为局部静态变量是一个在函数调用后保留其值的局部变量。

例如，下面的代码演示了局部静态变量的作用。

void TestStaticVar()

{

static int slocal = 10; //定义一个局部静态变量

printf("%d\n",slocal); //输出变量

slocal++; //自加 1

}

void main()

{

//连续 3 次调用 TestStaticVar

TestStaticVar();

TestStaticVar();

TestStaticVar();

}

执行上述代码，效果如图 1 所示。

图 1 局部静态变量

上述代码 3 次调用了 TestStaticVar 函数，在每次函数调用结束后，局部静态变量 slocal 都将保留。并且对于局部静态变量只初始化一次，因此每次调用 TestStaticVar 函数输出的值是不同的。

对于全局静态变量，它的作用域仅限于当前定义的文件，不能够被其他文件使用 extern 关键字访问。可以认为全局静态变量只是半个全局变量（不能够被其他文件共享）。

l register 存储类型

在定义变量时，使用 register 关键字，表示变量将被放置在 CPU 的寄存器中。与普通变量不同的是，访问 register 变量要比访问普通变量快很多。register 变量只能用于局部变量或作为函数的形式参数，而不能够定义全局的 register 变量。下面的代码定义了一个 register 变量。

register int slocal = 10;

对于寄存器变量，程序中不能够获得变量的地址，也不能够成为全局变量或静态变量，但是它可以作为函数的形式参数。

寄存器变量不能够保证将变量放置在寄存器中，也不能保证提高访问速度，它只是对编译器的一个“建议”。如今的编译器都具有优化功能，它会自动地调整变量的放置，因此，在程序中建议避免使用寄存器变量。

l auto 存储类型

变量的存储方式主要有两种，静态存储和动态存储。全局变量、静态变量均属于静态存储，而普通的局部变量属于动态存储。auto 关键字表示变量将被动态存储。默认情况下的局部变量均属于 auto 变量（也被称为自动变量）。定义一个全局的 auto 变量的非法的，因为全局变量属于静态存储，与 auto 变量的相互冲突的。

注意：在定义变量时不能够同时使用 register、extern、static 和 auto4 个关键字中的任意两个关键字。因此语句“static register int nData = 10;”的定义是非法的。