当前位置: 首页 > news >正文

嵌入式开发基础知识补充—内存的种类和C语言变量的存储位置(非易失性存储和易失性存储)

我们就用一个''开公司''的比喻,来帮你彻底搞懂它们的关系。

第一部分:硬件基础 - 公司的“仓库”与“办公室”

在MCU这个微型“公司”里,有两种最核心的物理资产:FlashSRAM

Flash (闪存) - 公司的“档案仓库”
  • 是什么? Flash是一种非易失性存储器 (Non-Volatile Memory)

  • 核心特性:“非易失”意味着断电后数据不会丢失。就像仓库里的档案柜,即使公司下班断电了,第二天来文件还在里面。

  • 作用:

    1. 存放程序代码 (Code): 你编译后生成的.bin.hex文件,也就是MCU要执行的所有指令,都烧录在这里。这是公司的**“操作手册和规章制度”**。

    2. 存放常量数据 (Constant Data): 代码中定义的常量,比如const int a = 100;或者字符串"Hello World",也存放在这里。这些是**“不可更改的档案资料”**。

  • 特点:

    • 容量大: 通常MCU的Flash容量会比SRAM大很多(如512KB Flash vs 128KB SRAM)。

    • 速度慢: CPU读取Flash的速度远慢于读取SRAM。

    • 擦写次数有限: Flash有写入寿命限制(通常是1万到10万次),不适合频繁改写。

SRAM (静态随机存取存储器) - 公司的“办公区工位”

  • 是什么? SRAM是一种易失性存储器 (Volatile Memory)

  • 核心特性:“易失”意味着断电后数据会瞬间全部丢失。就像办公桌,下班人走清空,第二天来是干净的。

  • 作用:

    1. 存放变量 (Variables): 程序运行时,所有需要被修改、计算、暂存的数据,都放在SRAM里。这是员工(CPU)进行日常工作的**“办公桌面”**。

    2. 作为函数调用栈 (Stack): 函数调用、参数传递等,都在这里进行。

  • 特点:

    • 容量小: 因为其物理结构复杂且昂贵,容量通常比Flash小。

    • 速度极快: CPU可以直接高速读写SRAM,几乎没有延迟,保证了程序的运行效率。

    • 擦写次数近乎无限: 可以随意、频繁地读写。

总结一下硬件的区别:

特性Flash (仓库)SRAM (办公室)
断电后数据保留 (非易失)丢失 (易失)
主要用途存储程序常量存储变量运行状态
读写速度极快
容量大小
擦写寿命有限近乎无限

导出到 Google 表格


第二部分:C语言映射 - “员工”如何使用“仓库”和“办公室”

现在,我们来看看你写的C代码,是如何被分配到Flash和SRAM这两块地方的。MCU程序运行时的内存(主要是SRAM),通常被划分为以下几个区域:

存放在SRAM (办公室) 的内容:
  1. .data段 (已初始化数据段)

    • 存放什么: 全局变量和静态变量(static),且被初始化为非零值

    • C语言示例: int global_var = 100; static int static_var = 50;

    • 工作流程: 这些变量的初始值10050其实是先存放在Flash里的。MCU上电后,在执行main函数之前,会有一段启动代码先把这些值从Flash拷贝到SRAM的.data段。就像上班前,员工从仓库档案柜里拿出今天要用的资料,放到自己的办公桌上。

  2. .bss段 (未初始化数据段)

    • 存放什么: 全局变量和静态变量,但它们没有被初始化被初始化为0

    • C语言示例: int global_uninit_var; static int static_zero_var = 0;

    • 工作流程: 启动代码在初始化.bss段时,会直接把它整块区域清零。这样做可以节省Flash空间,因为不需要在Flash里存储一大堆的0。

  3. Heap (堆)

    • 存放什么: 程序动态申请的内存。

    • C语言示例: 通过malloc(), calloc()等函数申请的内存空间,用完后需要free()手动释放。int* p = (int*)malloc(4); 这里的p本身是个局部变量在栈上,但它指向的那4个字节的内存在堆上。

    • 特点: 堆是动态的、不连续的,使用不当容易产生内存碎片或泄漏。在很多裸机MCU项目中,为了稳定性和实时性,会尽量避免使用堆。

  4. Stack (栈)

    • 存放什么:

      • 函数的局部变量: void func() { int local_var = 10; }

      • 函数的参数

      • 函数的返回地址

    • 工作流程: 栈是一个“先进后出”的结构。每调用一个函数,系统就会在栈顶为它分配一块空间(称为“栈帧”)来存放它的局部变量等信息。函数返回时,这块空间会被自动释放。这是由编译器自动管理的,效率极高。

存放在Flash (仓库) 的内容:
  1. .text段 (代码段)

    • 存放什么: 程序的二进制代码。你编写的所有函数,最终都会变成机器指令存放在这里。

  2. .rodata段 (只读数据段)

    • 存放什么: 只读的常量数据

    • C语言示例: const int const_var = 10; 以及字符串字面量,如 printf("Hello World"); 里的"Hello World"

// a.c 文件
#include <stdlib.h>const int g_const_var = 10;        // 存放在 Flash 的 .rodata 段
char* g_str = "Hello";             // g_str 指针本身在 .data 段 (SRAM)// "Hello" 字符串常量在 .rodata 段 (Flash)int g_init_var = 100;              // 存放在 SRAM 的 .data 段 (初始值100来自Flash)
static int s_uninit_var;           // 存放在 SRAM 的 .bss 段 (上电后被清零)void my_func(int param) {          // 函数代码本身在 Flash 的 .text 段int local_var = 20;            // local_var 和 param 都在 SRAM 的 栈(Stack)上int* heap_var = (int*)malloc(4); // heap_var指针在栈上, 指向的那4字节在堆(Heap)上*heap_var = 30;free(heap_var);
}int main(void) {my_func(g_init_var);return 0;
}

全局变量存储在哪里?

全局变量的存储位置取决于它是如何被定义的,主要分为以下三种情况:

1. 已初始化的全局变量 (Initialized Global Variables)

这种变量在定义时就被赋予了一个非零的初始值。

  • C语言示例:

    C

    int g_init_var = 100;
    char g_char_array[] = "Hello";
    
  • 存储位置: 运行时存储在 SRAM.data

  • 详细说明: 它的初始值(比如100"Hello")是固化在Flash里的。当MCU上电启动时,在进入main函数之前,一段特殊的启动代码会负责把这些初始值从Flash拷贝到SRAM中的.data段区域。程序在运行时,实际读写的是SRAM中的这个变量。


2. 未初始化 或 初始化为0的全局变量 (Uninitialized or Zero-Initialized Global Variables)

这种变量在定义时没有初始值,或者初始值为0。

  • C语言示例:

    C

    int g_uninit_var;
    static int g_zero_var = 0;
    
  • 存储位置: 运行时存储在 SRAM.bss

  • 详细说明: 为了节省Flash空间,编译器并不会在Flash里存储这些变量的初始值(0)。启动代码在初始化.bss段时,会直接将这整块内存区域全部清零。


3. const 修饰的全局常量 (const-qualified Global Constants)

这种变量被const关键字修饰,意味着它的值在程序运行期间不能被修改。

  • C语言示例:

    C

    const int g_const_var = 10;
    const char* message = "This is a constant string";
    
  • 存储位置: 直接存储在 Flash.rodata (只读数据) 段

  • 详细说明: 因为它的值是只读的,没有必要在运行时把它拷贝到宝贵的SRAM中。CPU在需要读取这个常量时,会直接从Flash中读取。

总结表格

为了方便您记忆,这里有一个清晰的总结:

变量定义示例运行时存储位置内存区域 (Section)
int g_init_var = 100;SRAM.data
int g_uninit_var;SRAM.bss
const int g_const_var = 10;Flash.rodata

核心要点回顾: 只要不是const修饰的全局变量,它在程序运行时最终都会存在于SRAM中,以便于程序进行快速的读写操作。区别仅在于它的初始值是如何被加载的。

http://www.dtcms.com/a/466640.html

相关文章:

  • 沈阳妇科排名前十的医生seo关键词排名优化
  • 读写分离架构:数据访问层的演进与实践
  • 应用最广网站建设技术wordpress被百度收录
  • Shell 编程1
  • conv([1 1], [1 2]) % 输出 [1 3 2](对应 (x+1)(x+2) = x²+3x+2)
  • SpringBoot 集成 LangChain4j RAG
  • linear protocol(线性协议)
  • net网络网站建设wordpress修改语言包目录
  • 购物网站建设的意义与目的镇江市建设工程安全监督站网站
  • UiKit中使用DiffableDataSource进行数据差异化更新
  • Elegant Query
  • 中小企业网站建设信息小企业想做网站推广找哪家强
  • 4A 架构之业务架构、数据架构、应用架构和技术架构
  • FOC电机控制原理
  • linux网络服务+linux数据库7
  • 阿里去可以做几个网站一线设计公司
  • 怎么面试一个网站开发的人wordpress 标签seo插件
  • 跨服务器快速传输数据
  • 一人AI自动化开发体系(Cursor 驱动):从需求到上线的全流程闭环与实战清单
  • Google 智能体设计模式:记忆管理
  • 大兴企业官网网站建设报价网站推荐界面
  • 精准核酸检测
  • 摩尔信使MThings入门教程3
  • 电子商务与网站建设报告福建建设工程信息网
  • 银座商城官网镇江seo网站优化
  • 网站建设好公司好做cps的网络文学网站
  • 廊坊做网站公司排名四川省住房和建设厅官方网站
  • 17.链路聚合——LACP模式(2025年10月10日)
  • PG数据文件位置迁移
  • 优化百度网站企业vi设计策划书