3.static.md 4.0 KB

static

判别规则(核心,唯一要记的)

  • 看到 static,先看它加在谁身上
    • 加在局部变量 → 改存储期:变量活整个程序期,跨调用保留值,只初始化一次
    • 加在全局变量或函数 → 改链接性:从"整个工程可见"缩成"本文件可见"(类似 C++ private)

一句话:"static 只改一件本来可变的事——局部变量延长寿命,全局/函数锁进文件。"

抽象描述(一句话本质)

static 管两件独立的事:存储期(活多久)链接性/作用域(谁能看到)。它不碰读写权限——static ≠ 只读。

正反例(建立直觉)

  • 正例1void f(){ static int cnt = 0; cnt++; } 连续调 3 次 → cnt = 1、2、3。普通局部变量每次重新创建永远是 1;static 版本活在静态数据区,只初始化一次,跨调用保留值
  • 正例2file1.cstatic int secret = 5; static int helper(){...} → 只有 file1.c 能看到/调用,file2.c 想用会报错;file2.c 定义同名也不冲突
  • 反例1:以为 static 局部变量 = 全局变量 → 错,作用域还是函数内,只是"活得更久"
  • 反例2:以为 static 全局变量改变了存储期 → 错,全局变量本来就活程序期,static 只是把"外部可见"改成"文件内可见"

易混对比

局部变量 + static 全局变量/函数 + static
改变了什么 存储期(auto → 程序期) 链接性(外部 → 内部)
生命周期 变长(跨调用保留值) 不变(本来就程序期)
可见范围 不变(还是函数内) 变窄(锁进文件内)
典型考点 计数器跨调用累加 文件私有变量/函数

变体验证(3 题,全过=学会)

  1. int next(void){ static int n=0; return n++; } 连续调用 3 次 → 返回 0、1、2(n++ 后置自增:先返回旧值再自增;static n 默认从 0 开始只初始化一次)
  2. a.cb.c 各定义 static int id = 1;不冲突(内部链接,各用各的)
  3. 陷阱题:函数里 static int x; 每次调用在栈上重新分配 → 。static 局部在静态存储区,程序启动分配一次,不随调用回收

口述要点(面试怎么讲)

  • 结论先行:static 加在局部变量 → 改存储期;加在全局/函数 → 改链接性
  • Q1 内存区别:static 局部变量和普通全局变量内存上没区别,都住静态存储区;区别只在"谁看得见"——static 局部 = 全局的寿命 + 局部的私密性
  • Q2 Flash vs RAM:static ≠ 只读。static 变量可改(如计数器),必须放 RAM;只有 const 才放只读段 Flash/rodata;static const 组合才能放 Flash
  • Q3 链接器为什么不起冲突:每个 .c 编译成独立 .o,static 符号标记为内部符号,只登记在 .o 自己的内部名单,不进全局符号表;链接器只认全局符号表,看不到内部 x → 各用各的。类比:两家公司各有一个"小李",只在内部花名册,外部目录没有,永不搞混
  • 易错点n++ vs ++n——return n++; 先给旧值(0,1,2),return ++n; 先自增(1,2,3)

关系网络

相邻概念 和 static 的关系 孤立理解会犯的错
const static 管"活多久/谁可见",const 管"能不能改"。只有 static const 才放 Flash 以为 static 自带只读/放 Flash
extern 正好相反:static = 内部链接(锁文件内),extern = 外部链接(跨文件共享) 以为 extern 能突破 static——不能,链接器根本不看内部符号
volatile 一个文件里被中断改的 static 计数器 → static + volatile 叠用 以为 static 自带中断安全
全局变量 内存同住静态区,区别只在可见范围 以为 static 局部是"更全局"的全局变量

学习日期

2026-08-03


每主题一页,复习时只翻本目录。