首页 > 系统相关 >【嵌入式编程】内存分布

【嵌入式编程】内存分布

时间:2025-01-05 14:34:43浏览次数:1  
标签:存储 const 常量 int 编程 嵌入式 内存 字符串 world

一、内存分布图

在操作系统中,内存被组织和管理以支持进程的运行。以下是一些常见的内存分布概念:

【内核空间】:操作系统内核使用的内存区域,用于存储内核代码、数据结构和进程控制块(PCB)。

【用户空间】:存储用户的代码。

    未初始化变量区(.bss):存放未初始化的全局变量和静态变量。

    已初始化变量区(.data):存放已初始化的全局变量和静态变量。

    常量区(.rodata):存储程序中定义的所有字符串常量和其他被const修饰的全局变量。

    栈区(.stack):用于函数调用时存储局部变量、参数和返回地址,空间通常向下增长(由高地址向低地址)。

    堆区(.heap):用于动态内存分配,如 C 语言中的malloc或 C++中的new,空间通常向上增长(由低地址向高地址)。

    数据区:存储全局变量、被const修饰的全局变量和被static修饰的静态变量。

    文本区(.text):存储程序代码,通常是只读的,也就是只有访问权而没有写入权。

注意事项:

在 C 语言言中常量有很多种,比如常见的:

字符常量:'a','A','*'。

字符串常量:"helloworld","ilovechina","12345"。

整常量:25,10,012,0x0a,0b00001010。

浮点常量:3.14,123.456,3.0E-23。

但并不是所有的常量都会被编译器放在常量区的,例如:

#include <stdio.h>

int main(void)
{
    int i = 10;
    return 0;
}

代码中定义了一个整型局部变量i,并被初始化为了 10,其中i是变量,10是常量,但编译器并不将10放入常量区,而是在汇编指令中直接通过立即数赋值。

这是因为编译器认为普通的整型、浮点型或字符型常量所占空间很小,使用起来很简单,认为将它们直接嵌入到代码中,而不是单独存储在常量区,这样会更加高效。如此节省了运行、访问的时间和存储空间。

二、那什么样的数据才将放入常量区(.rodata)呢?

1、字符串常量

#include <stdio.h>

int main(void)
{
    char *p = "hello world";
    return 0;
}

对于上方代码片段中的指针 char *p = "hello world";,指针 p 存储在栈上,

"hello world"字符串被放置在程序的常量区(.rodata) 中,指针 p 指向字符串常量 "hello world" 在常量区(.rodata)中的地址。

这是因为字符串字面量在程序的整个生命周期内不会改变,因此放在常量区(.rodata)可以节省内存并提高效率。

但是,当一个字符常量串被用来为数组初始化的时候,那么该字符串常量将不被放入常量区,而是放入对应的数组中,也就是数据区(.data)中。

例如:

#include <stdio.h>

int main(void)
{
    char str[20] = "hello world";
    return 0;
}

对于数组char str[20] = "hello world";,字符串常量 "hello world" 本身是存储在 .text区,但在初始化的过程中,该字符串会被复制到 str 数组中。这意味着字符串的实际内容会存储在 str 数组所在的内存区域,即在程序的数据段中(通常被称为.data区)。

两者不同的地方在于指针 p 本身存储在栈上,指向只读数据段中的字符串常量,而数组 str 存储在数据段中,并包含字符串常量"hello world"的副本。

2、 被const修饰的全局变量

#include <stdio.h>

const int value_0 = 10;
int value_1 = 20;

int main(void)
{
    const int value_2 = 30;
    return 0;
}

value_0全局变量被const修饰,所以被存储在常量区(.rodata)中;而value_1变量虽然也是全局变量,但并没有被const修饰,所以存储在了(.data)中。

但并不是所有被const修饰的变量都存储在常量区(.rodata),例如value_2变量是局部变量,被const修饰后仅仅意味着在表达式上不能显式地更改变该变量的值,否则语法错误,但该变量仍存放在栈区。

原创 ZRQRS 知睿电子工程师

标签:存储,const,常量,int,编程,嵌入式,内存,字符串,world
From: https://www.cnblogs.com/o-O-oO/p/18653331

相关文章

  • 重生之我在异世界学编程之数据结构与算法:深入数和二叉树篇
    大家好,这里是小编的博客频道小编的博客:就爱学编程很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!目录一、树的基本概念二、二叉树的基本概念三、在C语言中实现二叉树快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞......
  • 【嵌入式开发】线程安全与可重入的区别
    一、线程安全线程安全(ThreadSafety)指的是在多线程环境中,程序的行为符合预期,不会出现数据不一致或状态不可预测的情况。反之,则是线程不安全。线程安全问题主要来源于共享资源的并发访问,特别是当多个线程尝试修改同一资源时,如果没有适当的同步机制,就可能导致竞态条件(RaceConditi......
  • 面向对象编程
    一、面向过程与面向对象面向过程(POP)与面向对象(OOP)面向对象:ObjectOrientedProgramming面向过程:ProcedureOrientedProgramming2.面向对象的三大特征封装(Encapsulation)继承(Inheritance)多态(Polymorphism)3.面向对象的思想概述程序员从面向过程的执行者转......
  • 第二章 内存寻址
    1.内存地址逻辑地址、虚拟地址、线性地址、物理地址,它们是很绕的逻辑,有些和Intel绑定的概念,没有必要完全区分;可以认为,地址包括:虚拟地址和物理地址两种。 1.1.逻辑地址程序编译后的地址 1.2.线性地址程序运行时的内存地址 1.3.物理地址内存总线上的地址如......
  • 升级服务器数据盘大小、内存和CPU是否会丢失数据
    用户计划升级服务器的数据盘大小、内存和CPU,但担心这些操作会导致现有数据丢失。特别是对于网站程序和数据库文件的安全性表示担忧。解决方案:问题解决方案升级数据盘是否会丢失数据正常情况下,升级数据盘不会导致数据丢失。只要按照正确步骤操作,原有数据将保持完整。......
  • Python函数:编程的基石
    Python是一种非常灵活且强大的编程语言,其功能丰富,应用广泛。在Python的世界里,函数是构建程序的基本单元,它封装了一段代码,使其可以被重复调用和复用。本文将从函数的基本概念、定义、参数传递、返回值、作用域、高级特性等方面,深入探讨Python函数的奥秘,帮助读者掌握这一编程利器......
  • 12.30 java网络编程之socket编程(NIO多路复用版本) socket编程大作业答案
    在本次项目中,我们将实现一个简单的客户端-服务器(Client-Server)通信模型。通过这个项目,你将学习到如何使用Java的SocketCh和ServerSocket类来创建网络连接,进行数据的发送和接收。该项目不仅涵盖了Socket编程的基础知识,还将帮助你理解网络通信中的重要概念,如TCP/IP协议、阻塞......
  • PL/SQL语言的并发编程
    PL/SQL语言的并发编程引言在现代数据库应用中,通常需要处理大量的数据,并发编程成为了提升系统性能的有效手段。PL/SQL(ProceduralLanguage/SQL)作为Oracle数据库的一种过程化语言,具备强大的数据处理能力。在大规模数据处理和事务管理中,PL/SQL的并发编程能力显得尤为重要。本......
  • Python语言的编程范式
    Python语言的编程范式Python是一种广泛使用的高级编程语言,它因其简单易读的语法和强大的功能而受到程序员的喜爱。自1991年由荷兰人GuidolvanRossum首次发布以来,Python的发展迅速,其应用范围涵盖了Web开发、数据分析、人工智能、科学计算、自动化等多个领域。本文将深入探......
  • 2025年第16届蓝桥杯嵌入式竞赛学习笔记(二):点亮LED
    1.新建工程使用第一章配好的STM32CubeMX和Keil52.查看数据书册及图形化配置打开CT117E-M4产品手册查看LED灯的原理图LED的引脚为PC8-PC15,引脚为低电平时LED点亮U1为锁存器,锁存器的使能端PD2为高电平时,LED灯才会被点亮正确点灯步骤:①先PD2输出高电平②PC8-PC15输出低......