一句话:"有字进 data,全零进 bss;Flash 装代码和初值,RAM 装可变和动态。"
程序编译链接后的内存布局分六块:.text(指令)、.rodata(const)、.data(有初值变量)、.bss(零初值变量)、堆、栈。判据核心 = "这段数据会不会变"——不变的进 Flash,会变的进 RAM。
int g = 5; static int s = 10; 有非零初值 → 初值存 Flash,启动时拷到 RAM 的 .data 副本(RAM 才能改)int g; static int s = 0; → 启动清零,不占 Flash(初值全 0 不用存)→ 省 Flashint g = 0; → BSS!"初始化为 0"和"未初始化"在段里是一家| 段 | 存什么 | 初始化 | 嵌入式位置 |
|---|---|---|---|
| .text 代码段 | 机器指令 | — | Flash,只读 |
| .rodata 只读数据 | const 常量 | — | Flash,只读 |
| .data 数据段 | 已初始化非零的全局/static | 有初值,启动拷贝 | 初值 Flash,运行 RAM |
| .bss | 未初始化/初始化为 0 的全局/static | 启动清零 | RAM(不占 Flash) |
| 堆 | malloc | — | RAM,动态 |
| 栈 | 局部变量 | — | RAM,动态 |
static int counter = 0;(函数内)→ BSS(初值 0,"初始化为 0"和"未初始化"是一家)int arr[1000]; → 不占 Flash(BSS 在 RAM 清零)启动流程(Q3 完整版,面试必背):
上电 → 复位向量 → 设置栈指针 SP → 拷贝 .data 初值(Flash→RAM) → 清零 .bss → 跳转 main()
注意:MCU 上代码直接从 Flash 执行(XIP),没有 PC 那种"加载到内存"的步骤
易错点:int g = 0; 进 bss 不是 data;const 进 rodata 不是 data;忘了启动流程里的 SP 初始化
| 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 |
|---|---|---|
| 内存分配方式 | 三区 → 六段完整版:分段图就是"静态区"的细分 | 以为静态区只有一块,分不清 data/bss/rodata |
| 启动流程 | 上电 → 拷 data → 清 bss → main,就是分段图的"用法" | 忘了 SP 初始化这一步 |
| const | const 进 rodata,不改 → 直接 Flash,省 RAM | 以为 const 进 .data |
| 结构体对齐 | 段内数据怎么摆放 | 以为分段和段内布局无关 |
2026-08-03
每主题一页,复习时只翻本目录。