C 语言 static的用法 static分三大使用场景局部变量、全局变量、函数作用核心只有两点修改存储周期变量生命周期延长至整个程序运行期间修改作用域可见性限制作用域仅当前.c文件内部一、static 修饰局部变量函数内部1. 普通局部变量 vs static 局部变量void test() { int a 0; // 普通局部变量栈存储函数调用结束销毁 static int b 0; // static局部变量静态存储区程序结束才销毁 a; b; printf(a%d, b%d\n, a, b); } int main() { test(); // a1, b1 test(); // a1, b2 test(); // a1, b3 return 0; }2. 核心特性初始化只执行 1 次static int b0;仅程序启动时初始化一次后续重复调用函数不会重新赋值普通变量每次进函数都重新创建赋值。存储位置不同普通局部栈stack函数退出释放每次调用重新分配static 局部静态全局区data 段全局生命周期作用域不变依然只能在当前函数内访问外部无法读取 / 修改。默认自动初始化为 0不写赋值static int x;x 初始就是 0普通局部变量不初始化是随机垃圾值。3. 典型用途函数计数、记录上次调用状态、只初始化一次的缓存数据// 只打印一次提示 void log_once() { static int flag 0; if (!flag) { printf(程序启动日志\n); flag 1; } }二、static 修饰全局变量函数外部1. 不加 static 全局变量// file1.c int num 10; // 全局变量外部文件可跨文件访问 // file2.c extern int num; // 声明后就能使用file1的num2. 加 static 全局变量// file1.c static int num 10;作用域限制文件内私有仅当前.c文件可见其他.c文件用extern也无法访问、不能重定义同名变量。存储周期不变依旧存静态区程序全程存在默认初始 0。3. 作用多文件开发时隔离文件私有全局变量避免全局命名冲突。三、static 修饰函数函数定义前// file1.c static void func() { printf(私有函数\n); }作用域限制函数仅当前.c文件可用外部文件无法调用不能用extern声明。用途封装模块内部工具函数对外隐藏实现减少命名污染。对比无 static 函数普通函数是全局可见全工程可调用。四、static 三大场景对比总结表修饰对象存储位置生命周期作用域初始化规则普通局部变量栈 stack单次函数调用当前函数每次调用重新初始化默认随机值static 局部变量静态数据段整个程序运行当前函数仅初始化 1 次默认 0普通全局变量静态数据段整个程序运行整个工程所有文件程序启动初始化默认 0static 全局变量静态数据段整个程序运行仅当前.c 文件程序启动初始化默认 0普通函数代码段程序运行全工程可调用-static 函数代码段程序运行仅当前.c 文件可调用-五、常见易错点1.static 局部变量的初始化不能放表达式里动态赋值void test() { int n 5; static int x n; // 编译报错static初始化必须是常量 }2. static 变量不支持递归重置状态 递归调用同一个函数static 变量会持续累加不会每次递归清零。3. static 不能修饰函数形参void func(static int a) // 语法错误不允许4. 头文件定义 static 变量会出现多副本 如果在.h写static int x;每个包含该头文件的.c都会生成一份独立 x互不干扰。六、综合实战示例示例 1static 局部实现计数器#include stdio.h int get_cnt() { static int cnt 0; cnt; return cnt; } int main() { printf(%d\n, get_cnt()); //1 printf(%d\n, get_cnt()); //2 printf(%d\n, get_cnt()); //3 return 0; }示例 2多文件 static 隔离模块化// math.c static int cache 0; // 仅math.c内部可用 static void reset() { // 内部私有函数 cache 0; } int add(int a, int b) { cache a b; return cache; } // main.c #include stdio.h extern int add(int a, int b); int main() { printf(%d, add(2,3)); // cache、reset() 这里无法访问编译报错 return 0; }七、总结函数内 static 变量长存只初始化一次函数内独享文件外 static 全局 / 函数私有仅限当前.c外部看不见。