存储类(storage class)说明变量在何处分配、可见范围、生命周期以及未显式初始化时的默认值。C 语言中有 auto、static、register、extern 四类,其中 static 在静态存储相关章节亦有讨论。

四种存储类对照

存储类作用域默认初值存储位置生命周期
auto块内不确定(自动变量)内存(栈帧)至块结束
static块内或文件内0静态存储区至程序结束
register块内不确定可能位于寄存器至块结束
extern跨翻译单元0(全局对象)静态存储区至程序结束

auto:默认的局部变量

块内声明的变量默认为 auto,故该关键字很少显式写出:

int main(void) {
    auto int x = 10;
    printf("%d", x);
    return 0;
}

自动变量仅在声明所在的块内可见;未初始化时值不确定;离开块后所占栈空间可被复用。函数本身不使用 auto 存储类说明。

static:跨调用保留值的局部变量

块内 static 变量只初始化一次,之后各次进入该块仍保留上次的值:

void counter(void) {
    static int count = 0;
    count++;
    printf("Count = %d\n", count);
}

counter();   /* Count = 1 */
counter();   /* Count = 2 */

普通自动局部变量每次进入函数都会重新分配;static 局部变量存放在静态存储区,生命周期延续到程序结束。文件作用域的 static 还可限制符号仅在当前翻译单元内链接。

register:提示使用寄存器

register 向实现建议将变量放在寄存器中以提高访问速度:

register int i;
for (i = 0; i < 5; i++) {
    printf("%d ", i);
}

是否采纳由编译器决定;寄存器数量有限。对 register 对象取地址可能不被允许。现代编译器常自动完成寄存器分配,该关键字使用较少。

extern:引用其他翻译单元中的定义

多文件程序中,若变量在某文件中定义,其他文件可用 extern 声明以使用同一对象:

/* printVar.c */
int globalVar = 100;

/* main.c */
#include <stdio.h>
extern int globalVar;

int main(void) {
    printf("全局变量是 %d\n", globalVar);
    return 0;
}

编译链接示例:

gcc main.c printVar.c -o main

extern 声明不分配存储,仅说明标识符在别处已有定义。全局变量未初始化时默认为 0。

选用思路

  • 需在多次函数调用间保留局部状态 → 块内 static。
  • 使用定义在其他源文件中的全局对象 → extern 声明。
  • 普通局部变量、随块创建销毁 → 默认 auto(可省略关键字)。

本节归纳了四类存储类的差异。下一节结合程序内存布局说明栈、堆与各数据段如何承载不同存储类别的对象。