Skip to content

C 存储类

C 中的存储类说明符(storage class specifiers)定义了变量和函数的作用域(可见性)和生命周期(持续时间)。它们出现在声明或定义中的数据类型之前。

主要的存储类说明符有:

  • auto
  • register
  • static
  • extern

auto 是在函数或代码块内部声明的变量(局部变量)的默认存储类。它指定自动存储期(automatic storage duration)。

  • 作用域: 限于定义所在的块。
  • 生命周期: 进入块时创建,退出块时销毁。
  • 初始化: 不自动初始化;除非显式初始化,否则持有未定义值。
  • 用法: 很少显式使用,因为它是局部变量的默认存储类。
{
int count; // 隐式为 'auto int count;'
auto float sum = 0.0f; // 显式使用 'auto',效果相同
}

register 建议编译器将局部变量存储在 CPU 寄存器中以便更快访问,而非 RAM。

  • 作用域和生命周期: 与 auto 相同(局部于块,自动存储期)。
  • 存储: 提示使用寄存器;编译器不必须遵守。现代编译器通常会自动执行更好的寄存器分配。
  • 地址: 不能获取 register 变量的地址(不能使用 & 运算符),因为寄存器没有内存地址。
  • 用法: 很大程度上已过时。编译器通常能更好地优化。历史上用于频繁访问的变量,如循环计数器。
{
register int loop_counter; // 提示使用寄存器
// 不能这样做:&loop_counter
}

由于编译器经常忽略此提示,因此在现代 C 代码中通常不鼓励使用它。

static 根据上下文有两种主要用途:

  • 作用域: 限于定义所在的块(与 auto 类似)。
  • 生命周期: 静态存储期 (static storage duration)。 变量在程序整个执行期间都存在。它在函数调用之间保持其值。
  • 初始化: 只初始化一次(编译时或首次进入时)。如果未显式初始化,默认为零(或指针的 NULL)。
#include <stdio.h>
void counter_func(void) {
static int call_count = 0; // 只初始化一次
call_count++;
printf("函数被调用 %d 次。\n", call_count);
}
int main(void) {
counter_func(); // 输出:Function called 1 times.
counter_func(); // 输出:Function called 2 times.
counter_func(); // 输出:Function called 3 times.
return 0;
}

2. 函数外部 (全局变量和函数):

Section titled “2. 函数外部 (全局变量和函数):”
  • 作用域: 限制全局变量或函数的可见性(链接属性 linkage)到当前源文件(内部链接 internal linkage)。它不能直接从其他 .c 文件访问(即使使用 extern)。
  • 生命周期: 静态存储期(在程序执行期间存在)。
  • 初始化: 与全局变量相同(如果未显式设置则初始化为零/NULL)。
// --- file1.c ---
static int file_local_secret = 42; // 只在 file1.c 中可见
static void internal_helper(void) { // 只在 file1.c 中可调用
// ...
}
void public_interface(void) {
internal_helper();
file_local_secret++;
}
// --- file2.c ---
// extern int file_local_secret; // 错误:file_local_secret 具有内部链接属性
// extern void internal_helper(void); // 错误:internal_helper 具有内部链接属性
extern void public_interface(void); // 正确:public_interface 具有外部链接属性(默认)
int main(void) {
public_interface();
// 在这里无法访问 file_local_secret 或 internal_helper
return 0;
}

static 对于多文件项目中的封装(encapsulation)、隐藏实现细节至关重要。

extern 用于声明一个全局变量或函数,它定义在别处(通常在另一个源文件中)。它指示外部链接(external linkage)。

  • 目的: 提供对定义在另一个模块中的全局标识符的引用。
  • 作用域: 使全局标识符在当前作用域可见。
  • 生命周期: 引用一个具有静态存储期的变量。
  • 初始化: 不能初始化 extern 声明(初始化发生在定义处)。
// --- config.c ---
#include <stdbool.h>
const char* server_address = "192.168.1.100"; // 定义
bool logging_enabled = true; // 定义
// --- main.c ---
#include <stdio.h>
#include <stdbool.h>
// 声明在 config.c 中定义的变量
extern const char* server_address;
extern bool logging_enabled;
int main(void) {
printf("服务器:%s\n", server_address);
if (logging_enabled) {
printf("日志记录已开启\n");
}
return 0;
}

extern 对于在 C 项目中跨多个源文件共享全局变量和函数至关重要。