C程序运行内存模型——代码区、全局区、栈区、堆区上一节我们讲了栈像书桌抽屉自动管理堆像储藏室需要自己管理但是一个 C 程序运行时并不是只有栈和堆。一台电脑运行程序就像开了一座“大仓库”。这个仓库通常分成程序运行内存 ---------------------- | 代码区 | | 程序的指令 | ---------------------- | 全局区 | | 全局变量、静态变量 | ---------------------- | 堆区 | | new出来的数据 | | 动态申请空间 | ---------------------- | 栈区 | | 函数、局部变量 | | 参数 | ----------------------我们一个一个来看。一、代码区Code Segment1. 什么是代码区代码区存放程序执行的指令也就是我们写的 C 代码编译以后变成机器指令。例如#includeiostream using namespace std; int main() { coutHello; return 0; }电脑最终看到的不是coutHello;而是一堆机器语言101010101010 111000101010这些指令放在哪里答案代码区2. 代码区有什么特点特点1程序运行期间不会改变。比如int main() { coutHi; }这条打印命令不会突然变成coutBye;特点2多个变量可以执行同一份代码。例如100个学生对象小明 小红 小刚 ...它们调用eat()函数。不需要复制100份代码。大家共享代码区 eat()二、全局区Global Segment全局区存放程序开始就创建程序结束才消失的数据。主要包括全局变量静态变量1. 全局变量看代码#includeiostream using namespace std; int money100; int main() { coutmoney; return 0; }这里int money100;在函数外面。它叫全局变量存在哪里答案全局区。内存全局区 money1002. 局部变量 vs 全局变量比较int a10; int main() { int b20; }内存全局区 a10 栈 b20生命周期变量创建消失全局变量程序开始程序结束局部变量进入函数离开函数3. 静态变量 static看void fun() { static int count0; count; coutcount; }调用fun(); fun(); fun();输出1 2 3为什么因为普通变量int count;每次重新创建。但是static int count;只创建一次。存在哪里全局区。三、栈区Stack这是信奥最常见的区域。栈存局部变量函数参数函数调用信息1. 局部变量例如int main() { int a10; return 0; }内存栈 a10main结束自动删除。2. 函数参数例如void add(int x,int y) { int zxy; }调用add(3,5);栈栈 z8 y5 x3函数结束全部消失。3. 递归为什么使用栈看经典void dfs(int n) { if(n0) return; dfs(n-1); }调用dfs(3)栈第一次dfs(3)第二次dfs(2) dfs(3)第三次dfs(1) dfs(2) dfs(3)第四次dfs(0) dfs(1) dfs(2) dfs(3)这就是函数调用栈四、堆区Heap堆用于程序运行过程中动态申请空间。关键词new例如int *pnew int;内存栈 p | | ↓ 堆 1001. 堆的生命周期例如int *pnew int(10); cout*p; delete p;过程申请堆 10使用*p释放delete p消失。2. 为什么需要堆看情况1提前知道数量int a[100];可以。情况2不知道数量例如游戏玩家上午100人下午10000人怎么办不能Player a[10000];浪费。使用new Player();需要多少创建多少。五、四大区域综合例子看程序#includeiostream using namespace std; int total100; void test(int x) { static int count0; int a10; int *pnew int(50); } int main() { int b20; test(5); return 0; }分析1. 代码区存main() test()2. 全局区total100 count3. 栈区main:b20test:x5 a10 p4. 堆区50由new int(50)创建。画成图内存 代码区 main() test() ---------------- 全局区 total100 count ---------------- 堆区 50 ---------------- 栈区 p a10 x5 b20六、一个非常重要的问题指针变量在哪里很多学生会困惑int *pnew int;p在哪里答案p在栈*p指向的数据在堆。例如栈 堆 p --------- 100七、信奥竞赛中的应用1. DFS爆栈例如dfs(1000000)递归太深栈空间不足。解决改递归DFS ↓ 手写stack2. 大数组不要放栈错误int a[10000000];可能栈爆炸改vectorint a(10000000);或者static int a[10000000];3. 链表例如struct Node { int val; Node *next; }; Node *pnew Node;结构栈 p 堆 ------ |val | |next | ------这就是链表为什么需要堆。八、给同学们的最终记忆图C程序内存 代码区 电脑执行的步骤 | | 全局区 全局变量、static | | 堆区 new出来的大空间 | | 栈区 函数、小变量口诀代码区放命令全局区放长寿变量栈区放临时小变量堆区放动态大空间。九、和信奥算法的联系理解内存模型以后你会真正理解知识对应内存递归DFS栈BFS队列堆通常vector/queue动态扩展链表堆树节点堆图邻接表堆vector对象栈 数据堆全局数组全局区