单片机内存分配之 .data .bss .rodata段

本文介绍了单片机内存分配的三个关键段:.bss段用于存储未初始化或初始化为0的全局变量和静态局部变量;.data段存放初始化为非0的全局变量和静态局部变量;.rodata段则用于存储字符串和const常量。通过一个实验,详细解析了不同类型的变量在这些段中的分布情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念

.bss段

    存放没有初始化或者初始化为0的全局变量或者静态局部变量。

.data段

    存放初始化为非0,且非const属性的全局变量或者静态局部变量。

.rodata段

    存放字符串和const常量,一般只放在ROM中。

二、实验

1.工具链:

    GNU Tools ARM Embedded(win)

2.C代码:

    
int im_data = 3;                       
int im_bss;
int im_bss_0 = 0;
const int im_rodata = 1;
static int im_data_sta = 1;
static int im_bss_sta_0 = 0;
static int im_bss_sta;
char *im_rodata_str = "length_10";

int main(void){
	static int im_data_func = 1;
	static int im_bss_func;
	return 0;
}

3.测试过程

    1>make 产生elf文件

    2>arm-none-eabi-objdump -t elf 打印符号

<think>我们正在讨论C语言中.data的作用。根据引用[4]中的信息,在单片机C语言环境中,code和data有不同的作用:data区用于存储在RAM中且可被程序修改的数据,而code区则用于存储在ROM/Flash中的程序代码和常量。 在更广泛的C语言程序内存布局中,.data是程序的一个关键部分。它属于静态存储区,用于存储已初始化的全局变量和静态变量(包括静态局部变量)。这些变量在程序启动时就被加载到内存中,并一直存在直到程序结束。 引用[4]提到:“DATA区就没有什么选择了,肯定要放在RAM里面,放到rom里面改动不了。” 这说明.data必须位于可读写内存(RAM)中,因为其中的变量值在程序运行期间会被修改。与之相对的是.rodata(只读数据段),用于存储常量。 总结.data的功能和用途: 1. **存储内容**:已初始化的全局变量、静态全局变量和静态局部变量。 2. **存储位置**:位于可读写内存(RAM)中。 3. **生命周期**:从程序启动开始,直到程序结束才释放。 4. **初始化时机**:在程序加载到内存时由系统初始化(根据编译时指定的初始值)。 例如: ```c int global_var = 42; // 存储在.data static int static_var = 10; // 存储在.data void func() { static int local_static = 5; // 静态局部变量,存储在.data } ``` 注意:未初始化的全局变量和静态变量则存储在.bss(初始化为零),而.data仅包含显式初始化的变量。 **为什么需要.data?** - 程序需要持久存储某些全局状态(如配置参数、计数器等),这些状态在函数调用之间保持有效。 - 由于这些变量在程序启动时就初始化好,访问速度快(无需运行时额外初始化)。 **与其它的区别**: - **.text**:存放程序代码(指令)。 - **.rodata**:存放只读数据(如字符串常量)。 - **.bss**:存放未初始化或初始化为0的全局/静态变量。 引用[4]还提到单片机环境中程序通常从Flash加载到RAM运行,但.data直接位于RAM以保证可修改性。 §§相关问题§§ 1. C语言中.bss的作用是什么?与.data有何区别? 2. 如何查看C程序编译后的内存布局(如.data大小)? 3. 在嵌入式系统中,优化.data内存占用的方法有哪些? 4. 静态存储区(.data/.bss)和堆(heap)在生命周期管理上有何不同?</think>### C语言中`.data`的功能与用途详解 在C语言程序的内存布局中,**.data**(数据段)是存储**已初始化的全局变量和静态变量**的关键区域。其核心功能与用途如下: #### 1. **存储内容** - **显式初始化的全局变量** ```c int global_val = 10; // 存储在.data char *str = "Hello"; // 指针存储在.data(字符串内容在.rodata) ``` - **显式初始化的静态变量** ```c static int static_val = 20; // 静态全局变量 void func() { static int local_static = 30; // 静态局部变量 } ``` - **非零初始值的静态存储期变量** 所有在编译时已知非零初始值的持久性变量(引用[4]明确提到DATA区必须位于RAM)[^4]。 #### 2. **核心特性** | 特性 | 说明 | |--------------|----------------------------------------------------------------------| | **存储位置** | 可读写内存(RAM)中,**非ROM/Flash**(引用[4]强调"DATA区必须放在RAM")[^4] | | **生命周期** | 从程序启动到结束持续存在 | | **初始化** | 在**程序加载时**由系统自动初始化(非运行时) | | **访问速度** | 直接内存访问,速度快于堆区动态分配 | #### 3. **与其它内存的区别** ```mermaid graph LR A[程序内存布局] --> B[.text:代码] A --> C[.data:已初始化全局/静态变量] A --> D[.bss:未初始化全局/静态变量] A --> E[.rodata:只读常量] A --> F[堆:动态分配内存] A --> G[栈:局部变量] ``` - **vs .bss**:.bss存储**未初始化或零初始化**的全局/静态变量,不占用磁盘空间 - **vs .rodata**:.rodata存储**只读常量**(如字符串字面值),不可修改 - **vs 堆(heap)**:.data内存由系统管理,堆需手动分配释放 #### 4. **关键设计原因** 1. **持久性需求** 全局/静态变量需在程序整个生命周期保持状态(如配置参数、计数器)。 2. **快速访问** 直接RAM存储避免Flash读取延迟(引用[4]指出“读flash比读ram费时间”)[^4]。 3. **空间效率** 初始值直接编译进可执行文件,无需运行时额外初始化代码。 4. **可修改性** 与.rodata不同,.data变量允许程序运行时修改值。 #### 5. **嵌入式系统中的特殊考量** 在单片机等资源受限环境中: - DATA大小直接影响RAM需求(需在链接脚本中精确配置) - 过度使用.data可能导致RAM不足(尤其大量初始化数组时) - 优化策略:将只读数据移至.rodata,未初始化数据移至.bss > **示例场景**:嵌入式设备配置参数 > ```c > // 存储在.data(可修改的持久配置) > const float default_voltage = 3.3; // 错误!应放.rodata > int current_mode = 1; // 正确!.data可修改 > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值