变量存储属性
搞清存储期、链接与作用域,看透变量在内存中的安身规则
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
变量存储属性
搞清存储期、链接与作用域,看透变量在内存中的安身规则
为什么需要存储属性
CPU 一条指令一条指令往下走,每执行完一条都会产生中间结果——如果当下不落到某个地方,下一条指令就拿不到。这就是变量必须依赖存储的根本原因。
工人算完中间结果写上黑板,下道工序直接读;没黑板流水线就断了
四种存储类别总览
以根为中心向外辐射,四类分支各带两条核心特性。先看分支名记住身份,再看子节点理解行为。
存储类型决定什么
四种存储类别不只是一个标签,它们具体决定了变量的三个维度:作用域、生命周期、内存位置。选哪种类别,等于同时在做三个决策。
租期≈生命周期、能用哪些房间≈作用域、房子在哪≈内存位置——三件事随房型一起定
内存区域划分
程序内存的栈区、堆区、静态区、代码区分布
局部变量的本质
内存划分好后,最常见的一类变量——函数内部定义的局部变量——它们的「家」又在哪里?
入住分配、退房作废——对应当前调用栈帧;房卡信息被复刻带走(捕获)后,权限就逃出房间继续生效
局部变量代码示例
用 Python 直观演示局部变量的定义、每次调用重建的生命周期、以及作用域边界。
items 在函数内被定义;每次调用都创建一份新的,函数返回即被回收;连续两次调用拿到的列表互不相干;函数外访问触发 NameError,划清作用域边界。
全局变量的本质
上页说局部变量像办公桌抽屉——自己用自己管。但项目里多个函数往往要共享同一个数据,这时候就需要全局变量出场了。
白板放公共区,谁都能读能写,内容一直留着直到下班清理
全局变量代码示例
通过一份精简 C 代码,看清定义、extern 声明与初始化规则的真实差异。
L3 仅声明不占存储;L4 带初始化进 .data;L5 无初值仍是定义,运行时清零;L6 const 进入只读段;main 内可直接使用所有全局。
全局变量的副作用
上一页用代码展示了全局变量的便利——但便利的另一面就是失控。任何角落都能读写同一个值,四类麻烦就会冒出来。
所有人都能看能写,谁都敢擦,出错找不到责任人
局部 vs 全局变量
作用域、存储位置、生命周期、默认值——四个维度环环相扣,混用时定位 bug 极难。
- 作用域:限定在函数或代码块内
- 存储位置:栈(Stack)
- 生命周期:函数调用时创建,结束即销毁
- 默认值:未初始化则值不确定(栈垃圾)
- 作用域:整个程序可见,跨文件需 extern 声明
- 存储位置:静态存储区(数据段)
- 生命周期:程序启动到结束,与函数调用无关
- 默认值:自动初始化为 0
auto 存储类别
局部变量是函数里临时用的数据,它默认属于哪种存储类别?答案是 `auto`——而且通常你连这个关键字都不用写。
进入函数相当于入住分配房间,函数结束相当于退房,房间自动收回给下一个调用者
register 存储类别
请求将变量存储在寄存器中以加快访问,但不一定成功
static 局部变量
你已经见过 auto 和 register 局部变量。它们有个共同点:函数一返回就'蒸发'。static 局部变量偏要打破这个规矩。
只有室友能打开(作用域不变),但毕业典礼前不会被清理(生命周期延长)
static 局部变量示例
三次调用同一个 counter(),count 的值不归零,而是持续累加。
L4 的 static 让 count 只初始化一次;L10~L12 三次调用证明:每次进入 counter,count 都带着上次的值继续累加,不会归零。
static 全局变量
全局变量虽然贯穿整个程序,但任何 .c 文件都能 extern 引用——这太危险了。给全局变量加 static,等于给它装上文件级门禁:其他文件再也够不着它。
普通全局像大堂公告谁都改,static 后等于把公告搬进部门办公室——只有本部门能看能改
extern 存储类别
上页我们用 static 把全局变量关进当前文件。可工程里多个 .c 文件经常要共享同一个全局变量——这次得开门迎客。extern 就是那把开门钥匙。
原始文档在某 .c 文件真实存在(定义才分配存储),链接只是指向,多人收到同一链接都不额外占空间
extern 跨文件示例
两个文件,一份存储:file1 定义,file2 通过 extern 共享同一块内存。
第 4 行真正分配存储;第 14 行 extern 只是声明;第 18、19 行证明两文件操作同一块内存。
静态存储的过程
静态变量的完整生命周期:编译期划位、加载期落座、运行期驻守、结束期归还。
动态存储的过程
动态存储要求程序员手动完成申请、使用、释放三大阶段,每一步都不能漏。
生命周期全景对比
三条横向轨道分别画三种变量的生死节点;纵向对比同一时刻谁生谁亡。
存储类别完整对照表
四种存储类别的关键字、作用域、生命周期、存储位置四维对比
核心概念自测
在 C 语言中,函数体内声明的 static 变量,哪项描述最准确?
课程要点总结
- ✓作用域回答“在哪里可见”,生命周期回答“何时存在”
- ✓static 可延长局部变量寿命,也可限制全局符号可见性
- ✓extern 实现跨文件引用,但本身不分配存储
- ✓存储类别共同决定名称可见范围与对象生存区间
课后思考
先遮住答案区自己思考,想清楚再看右侧提示——课后琢磨比课上听懂更重要。
参考答案两种用法都围绕'改变存储/链接方式':局部 static 从栈搬到静态区(延长生命周期);全局 static 从外部链接改为内部链接(限制可见性)。对立表象下,机制是统一的。
参考答案头文件统一管理声明,避免每个 .c 重复写、漏写;extern 是声明不是定义,多次包含不冲突。若把定义放头文件,每个 .c 都会复制一份,链接时报重复定义错误。
参考答案其他语言用类/命名空间收窄可见性,把'全局'封装成受控接口。C 中类似思路:变量藏 .c 内、用 static 限为内部链接,只通过函数暴露读写——这是 C 版的模块化封装。