## 程序分段 ## 判别规则(核心,唯一要记的) - 判据一句话:**指令 → .text;const → .rodata;有非零初值的全局/static → .data;无初值或初值为 0 的全局/static → .bss;局部变量 → 栈;malloc → 堆** - 嵌入式核心:**RAM 要装 data 副本 + BSS + 堆 + 栈;Flash 只装 text + rodata + data 初值。BSS 不占 Flash = 省空间** 一句话:**"有字进 data,全零进 bss;Flash 装代码和初值,RAM 装可变和动态。"** ## 抽象描述(一句话本质) 程序编译链接后的内存布局分六块:.text(指令)、.rodata(const)、.data(有初值变量)、.bss(零初值变量)、堆、栈。判据核心 = "**这段数据会不会变**"——不变的进 Flash,会变的进 RAM。 ## 正反例(建立直觉) - **正例1(.text)**:机器指令,只读,Flash/ROM - **正例2(.data)**:`int g = 5; static int s = 10;` 有非零初值 → 初值存 Flash,启动时拷到 RAM 的 .data 副本(RAM 才能改) - **正例3(.bss)**:`int g; static int s = 0;` → 启动清零,**不占 Flash**(初值全 0 不用存)→ 省 Flash - **正例4(堆+栈)**:堆 = malloc 动态分配向上增长;栈 = 局部变量向下增长,函数调用期 - **反例1**:`int g = 0;` → BSS!"初始化为 0"和"未初始化"在段里是一家 - **反例2**:const 全局变量 → .rodata 不是 .data——不改就直接放 Flash,不用拷 RAM(省 RAM) ## 易混对比(六段) | 段 | 存什么 | 初始化 | 嵌入式位置 | | ---------------- | ------------------------------------- | ---------------- | --------------------- | | .text 代码段 | 机器指令 | — | Flash,只读 | | .rodata 只读数据 | const 常量 | — | Flash,只读 | | .data 数据段 | 已初始化**非零**的全局/static | 有初值,启动拷贝 | 初值 Flash,运行 RAM | | .bss | **未初始化/初始化为 0** 的全局/static | 启动清零 | RAM(**不占 Flash**) | | 堆 | malloc | — | RAM,动态 | | 栈 | 局部变量 | — | RAM,动态 | ## 变体验证(3 题,全过=学会) 1. `static int counter = 0;`(函数内)→ **BSS**(初值 0,"初始化为 0"和"未初始化"是一家) 2. 陷阱题:全局未初始化 `int arr[1000];` → **不占 Flash**(BSS 在 RAM 清零) 3. 陷阱题:启动代码对 .data 和 .bss 各做什么 → **.data 初值从 Flash 拷到 RAM;.bss 清零** ## 口述要点(面试怎么讲) - **结论先行**:六段(text/rodata/data/bss/堆/栈),判据 = "这段数据会不会变" - **为什么区分 .data 和 .bss**:BSS 初值全 0 不用存 Flash → **省 Flash 资源**。Flash 也是稀缺资源,少存一份 0 的初值就多一片空间 - **.rodata vs .data**:rodata 不改 → 直接 Flash 引用,**省 RAM**(不用拷贝副本);data 要改 → 必须拷贝到 RAM 才能改。const 进 rodata 不进 data 就是这个道理 - **启动流程(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 --- _每主题一页,复习时只翻本目录。_