08-块作用域的静态变量
12.1.6 块作用域的静态变量
静态变量(static variable)听起来自相矛盾,像是一个不可变的变量。实际上,静态的意思是该变量在内存中原地不动,并不是说它的值不变。具有文件作用域的变量自动具有(也必须是)静态存储期。前面提到过,可以创建具有静态存储期、块作用域的局部变量。这些变量和自动变量一样,具有相同的作用域,但是程序离开它们所在的函数后,这些变量不会消失。也就是说,这种变量具有块作用域、无链接,但是具有静态存储期。计算机在多次函数调用之间会记录它们的值。在块中(提供块作用域和无链接)以存储类别说明符 static (提供静态存储期)声明这种变量。程序清单12.3演示了一个这样的例子。
程序清单12.3 loc_stat.c 程序
/* loc_stat.c -- 使用局部静态变量 */
#include <stdio.h>
void trystat(void);
int main(void)
{
int count;
for (count = 1; count <= 3; count++)
{
printf("Here comes iteration %d:\n", count);
trystat();
}
return 0;
}
void trystat(void)
{
int fade = 1;
static int stay = 1;
printf("fade = %d and stay = %d\n", fade++, stay++);
}
注意, trystat() 函数先打印再递增变量的值。该程序的输出如下:
Here comes iteration 1:
fade = 1 and stay = 1
Here comes iteration 2:
fade = 1 and stay = 2
Here comes iteration 3:
fade = 1 and stay = 3
静态变量 stay 保存了它被递增 1 后的值,但是 fade 变量每次都是 1 。这表明了初始化的不同:每次调用 trystat() 都会初始化 fade ,但是 stay 只在编译 trystat() 时被初始化一次。如果未显式初始化静态变量,它们会被初始化为 0 。
下面两个声明很相似:
int fade = 1;
static int stay = 1;
第1条声明确实是 trystat() 函数的一部分,每次调用该函数时都会执行这条声明。这是运行时行为。第2条声明实际上并不是 trystat() 函数的一部分。如果逐步调试该程序会发现,程序似乎跳过了这条声明。这是因为静态变量和外部变量在程序被载入内存时已执行完毕。把这条声明放在 trystat() 函数中是为了告诉编译器只有 trystat() 函数才能看到该变量。这条声明并未在运行时执行。
不能在函数的形参中使用 static :
int wontwork(static int flu); // 不允许
“局部静态变量”是描述具有块作用域的静态变量的另一个术语。阅读一些老的C文献时会发现,这种存储类别被称为内部静态存储类别(internal static storage class)。这里的内部指的是函数内部,而非内部链接。