C 语言 static的用法
📅 2026/7/12 7:22:44
👁️ 阅读次数
📝 编程学习
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(); // a=1, b=1 test(); // a=1, b=2 test(); // a=1, b=3 return 0; }2. 核心特性
- 初始化只执行 1 次
static int b=0;仅程序启动时初始化一次,后续重复调用函数不会重新赋值;普通变量每次进函数都重新创建赋值。 - 存储位置不同
- 普通局部:栈(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 |
| 普通全局变量 | 静态数据段 | 整个程序运行 | 整个工程所有文件 | 程序启动初始化,默认 0 |
| static 全局变量 | 静态数据段 | 整个程序运行 | 仅当前.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,互不干扰。
六、综合实战示例
示例 1:static 局部实现计数器
#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,外部看不见。
编程学习
技术分享
实战经验