auto / register / extern / static

← C语言知识地图


核心:四个关键字控制变量的存储位置、生命周期和可见范围。

关键字存储位置生命周期作用域关键特征
auto函数执行期间块内局部变量默认值,几乎不显式写
registerCPU 寄存器(建议)函数执行期间块内不能取地址 &,编译器可能忽略
extern全局数据段整个程序运行期跨文件声明一个别处定义的变量/函数
static全局数据段整个程序运行期文件内 / 块内持久但不可跨文件访问

auto

void func(void) {
    auto int x = 1;  // 等价于 int x = 1;
}
  • 默认就是 auto,写了纯属多余
  • C 编译器唯一会默认加的存储类

register

register int counter;
for (counter = 0; counter < 1000000; counter++) { ... }
  • 请求编译器将变量放入 CPU 寄存器,减少内存访问
  • 不能取地址&counter 编译报错
  • 编译器有权忽略该建议(现代编译器优化已很智能)

extern

// file1.c
int global = 42;
 
// file2.c
extern int global;   // 声明:告诉编译器 global 在别处定义
void func(void) {
    global = 100;    // 操作的是 file1.c 里的同一个变量
}
  • 只声明不定义,链接时解析
  • 函数默认就是 externextern void foo(void);void foo(void); 等价

static

文件作用域(内部链接)

static int counter = 0;  // 仅在当前 .c 文件内可见
  • 其他文件同名变量互不冲突
  • 全局变量应尽量用 static 限制可见性

函数内(持久局部变量)

void count(void) {
    static int n = 0;  // 只初始化一次
    n++;
    printf("%d\n", n);
}
  • 值在多次调用间保持
  • 存储在全局数据段,生命周期 = 程序运行期

静态函数

static void helper(void) { ... }  // 仅当前文件内可调用