## static ## 判别规则(核心,唯一要记的) - 看到 static,先看它加在**谁身上**: - 加在**局部变量** → 改**存储期**:变量活整个程序期,跨调用保留值,只初始化一次 - 加在**全局变量或函数** → 改**链接性**:从"整个工程可见"缩成"本文件可见"(类似 C++ private) 一句话:**"static 只改一件本来可变的事——局部变量延长寿命,全局/函数锁进文件。"** ## 抽象描述(一句话本质) static 管两件独立的事:**存储期(活多久)**和**链接性/作用域(谁能看到)**。它不碰读写权限——static ≠ 只读。 ## 正反例(建立直觉) - **正例1**:`void f(){ static int cnt = 0; cnt++; }` 连续调 3 次 → cnt = 1、2、3。普通局部变量每次重新创建永远是 1;static 版本活在静态数据区,只初始化一次,跨调用保留值 - **正例2**:`file1.c` 里 `static 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.c`、`b.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 --- _每主题一页,复习时只翻本目录。_