C语言:内存分配---栈区、堆区、全局区、常量区和代码区

news2025/1/10 11:19:11

一、C语言内存分区

C语言内存分区示意图如下:
在这里插入图片描述

1. 栈区

栈区介绍
  • 栈区由编译器自动分配释放,由操作系统自动管理,无须手动管理。
  • 栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁
  • 栈区按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
  • 栈区先进后出原则,即先进去的被堵在屋里的最里面,后进去的在门口,释放的时候门口的先出去。
存放内容
  • 临时创建的局部变量const定义的局部变量存放在栈区
  • 函数调用和返回时,其入口参数返回值存放在栈区

2. 堆区

堆区介绍
  • 堆区由程序员分配内存和释放。
  • 堆区按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。
调用函数
  • malloc等函数实现动态分布内存。

    void *malloc(size_t);
    
    • 1

    参数size_t是分配的字节大小。
    返回值是一个void*型的指针,该指针指向分配空间的首地址。
    (void *型指针可以任意转换为其他类型的指针)

  • free函数进行内存释放,否则会造成内存泄漏。

    void free(void * /*ptr*/);
    
    • 1

    参数是开辟的内存的首地址。

3. 全局(静态)区

全局(静态)区介绍
  • 通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。
  • 全局区有 .bss段 和 .data段组成,可读可写。
.bss段
  • 未初始化的全局变量和未初始化的静态变量存放在.bss段。
  • 初始化为0的全局变量和初始化为0的静态变量存放在.bss段。
  • .bss段不占用可执行文件空间,其内容由操作系统初始化。
.data段
  • 已初始化的全局变量存放在.data段。
  • 已初始化的静态变量存放在.data段。
  • .data段占用可执行文件空间,其内容有程序初始化。

4. 常量区

  • 字符串数字等常量存放在常量区。
  • const修饰的全局变量存放在常量区。
  • 程序运行期间,常量区的内容不可以被修改。

5. 代码区

  • 程序执行代码存放在代码区,其值不能修改(若修改则会出现错误)。
  • 字符串常量和define定义的常量也有可能存放在代码区。

二、STM32存储器分配

1. 随机存储器—RAM

  • RAM是与CPU直接交换数据的内部存储器,也叫主存(内存)。
  • 它可以随时读写,而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介。
  • 当电源关闭时RAM不能保留数据(掉电数据消失哦)如果需要保存数据,就必须把它们写入一个长期的存储设备中(例如硬盘)。

2. 只读存储器—ROM

  • ROM所存数据,一般是装入整机前事先写好的,整机工作过程中只能读出,而不像随机存储器那样能快速地、方便地加以改写。
  • ROM所存数据稳定,断电后所存数据也不会改变。

本文使用是STM32F103芯片,keil V5环境下默认的内存配置见下图:
在这里插入图片描述

  • ROM区域是0x8000000开始,大小是0x10000,这片区域是只读区域,不可修改,存放代码区常量区
  • RAM区域是0x20000000开始,大小是0x5000,这片区域是可读写区域,存放的是全局(静态)区堆区栈区

该芯片的内部分区如下图所示:
在这里插入图片描述

三、基于STM32代码验证

1. 详细代码如下

#include "main.h"
#include <string.h> //用于字符串处理
#include <stdio.h>	//用于printf打印
#include <stdlib.h> //用于分配堆区---调用malloc和free

#include "delay.h"
#include "uart3.h"
#include "led.h"

//全局区
		int 	q1;		//未初始化全局变量
static 	int 	q2;		//未初始化静态变量	
const  	int   	q3;		//未初始化只读变量		

		int   m1=1;		//已初始化全局变量
static  int   m2=2;		//已初始化静态变量

//常量区
const   int   m3=3;		//已初始化只读变量
				
int main(void)
{
	SystemCoreClockUpdate(); //设置系统时钟为72M
	LED_GPIO_Config();
	Uart3_init();
	
	while(1)
	{
		//栈区	
		int 	 mq1;			//未初始化局部变量
		int  	*mq2;			//未初始化局部指针变量
			
		int   	mq3=3;		//已初始化局部变量	
		char 	qq[10] = "hello"; //已初始化局部数组
		
		const  	int   mq4;			//未初始化局部只读变量
		const   int   mq5=3;		//已初始化局部只读变量
				
		//堆区
		int *p1 = malloc(4);    //已初始化局部指针变量p1
		int *p2 = malloc(4);    //已初始化局部指针变量p2		
				
		//全局区
		static 	int 	mp1;			//未初始化局部静态变量	
		static  int   mp2=2;		//已初始化局部静态变量
	
		//常量区
		char *vv = "I LOVE YOU";//已初始化局部指针变量
		char *mq = "5201314";
	
		printf("\n栈区-变量地址\n");
		printf("未初始化局部变量 		:0x%p\r\n",&mq1);
		printf("未初始化局部指针变量		:0x%p\r\n",&mq2);
		printf("已初始化局部变量			:0x%p\r\n",&mq3);
		printf("已初始化局部数组			:0x%p\r\n", qq );
		
		printf("未初始化局部只读变量 		:0x%p\r\n",&mq4);
		printf("已初始化局部只读变量		:0x%p\r\n",&mq5);
		
		printf("\n堆区-动态申请地址\r\n");
		printf("已初始化局部int型指针变量p1   :0x%p\r\n", p1);
		printf("已初始化局部int型指针变量p2   :0x%p\r\n", p2);

		printf("\n全局区-变量地址\n");
		printf("未初始化全局变量 	:0x%p\r\n",&q1);
		printf("未初始化静态变量		:0x%p\r\n",&q2);
		printf("未初始化只读变量		:0x%p\r\n",&q3);
		
		printf("已初始化全局变量 	:0x%p\r\n",&m1);
		printf("已初始化静态变量		:0x%p\r\n",&m2);

		printf("未初始化局部静态变量	 :0x%p\r\n",&mp1);
		printf("已初始化局部静态变量	 :0x%p\r\n",&mp2);			
		
		printf("\n常量区地址\n");
		printf("已初始化只读变量		  :0x%p\r\n",&m3);
		printf("已初始化局部指针变量	  :0x%p\r\n",vv );
		printf("已初始化局部指针变量	  :0x%p\r\n",mq );
		
		printf("\n代码区地址\n");
		printf("程序代码区main函数入口地址	:0x%p\n", main);

		led485_flicker();
		delay_ms(1000);
		
		free(p1);
		free(p2);        
	}
}

2. 运行结果如下

栈区-变量地址
未初始化局部变量 		:0x20000654
未初始化局部指针变量		:0x20000650
已初始化局部变量			:0x2000064c
已初始化局部数组			:0x20000640
未初始化局部只读变量		:0x2000063c
已初始化局部只读变量		:0x20000638

堆区-动态申请地址
已初始化局部指针变量p1   	:0x20000060
已初始化局部指针变量p2   	:0x20000068

全局区-变量地址
未初始化全局变量 		:0x20000014
未初始化静态变量			:0x20000018
未初始化只读变量		 	:0x2000001c
已初始化全局变量 	 	:0x20000020
已初始化静态变量		 	:0x20000024
未初始化局部静态变量	 	:0x20000028
已初始化局部静态变量	 	:0x2000002c

常量区地址
已初始化全局只读变量	  	:0x080011a4
已初始化局部指针变量	  	:0x08000e78
已初始化局部指针变量	  	:0x08000e84

代码区地址
程序代码区main函数入口地址	:0x08000d6d

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1449296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务中台架构的设计与实现

本文将探讨微服务中台架构的设计与实现&#xff0c;介绍如何通过微服务的方式进行系统拆分和组合&#xff0c;构建灵活、可扩展且易于维护的中台架构&#xff0c;以加速企业的数字化转型和提升竞争力。 ## 1. 引言 随着企业规模的不断扩大和业务的日益复杂化&#xff0c;传统…

山西电力市场日前价格预测【2024-02-12】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-12&#xff09;山西电力市场全天平均日前电价为127.42元/MWh。其中&#xff0c;最高日前电价为369.24元/MWh&#xff0c;预计出现在18:45。最低日前电价为0.00元/MWh&#xff0c;预计出…

库函数strlen的实现

目录 一、原理二、思路三、实现 一、原理 库函数strlen的功能是求字符串长度&#xff0c;统计的是字符串中 \0 之前的字符的个数。 函数原型如下&#xff1a; size_t strlen ( const char * str );二、思路 参数str接收⼀个字符串的起始地址&#xff0c;然后开始统计字符串中…

WEB APIs(1)

变量声明const&#xff08;修饰常量&#xff09; const优先&#xff0c;如react&#xff0c;基本const&#xff0c; 对于引用数据类型&#xff0c;可用const声明&#xff0c;因为储存的是地址 何为APIs 可以使用js操作HTML和浏览器 分类&#xff1a;DOM&#xff08;文档对象…

C# Winform .net6自绘的圆形进度条

using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;namespace Net6_GeneralUiWinFrm {public class CircularProgressBar : Control{private int progress 0;private int borderWidth 20; // 增加的边框宽度public int Progr…

全闭环直播推流桌面分享远控系统

直播推流涉及多协议&#xff0c;多端技术栈和知识点&#xff0c;&#xff0c;想要做好并不容易&#xff0c;经过几年时间的迭代&#xff0c;终于小有成就&#xff0c;聚集了媒体服务器&#xff0c;实时会议sfu&#xff0c;远控kvm等功能。可以做一个音视频应用的瑞士小军刀。主…

为什么说技术进步很慢? —— 技术的先进性与其当下价值的不匹配

一、背景 技术进步是否缓慢是一个相对的概念&#xff0c;需要在不同的领域和时间段内进行分析。以下是一些不同领域中可能造成技术进步看似缓慢的原因&#xff1a; 1. **基础研究瓶颈**&#xff1a;许多先进技术的发展依赖于基础科学的突破&#xff0c;而这些突破往往需要长时…

openGauss学习笔记-219 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-网络

文章目录 openGauss学习笔记-219 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-网络219.1 查看网络状况 openGauss学习笔记-219 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-网络 获取openGauss节点的CPU、内存、I/O和网络资源使用情况&#xff0c;确认这些资源…

论文阅读-面向机器学习的云工作负载预测模型的性能分析

论文名称&#xff1a;Performance Analysis of Machine Learning Centered Workload Prediction Models for Cloud 摘要 由于异构服务类型和动态工作负载的高变异性和维度&#xff0c;资源使用的精确估计是一个复杂而具有挑战性的问题。在过去几年中&#xff0c;资源使用和流…

【机器学习笔记】3 逻辑回归

分类问题 分类问题监督学习最主要的类型&#xff0c;主要特征是标签离散&#xff0c;逻辑回归是解决分类问题的常见算法&#xff0c;输入变量可以是离散的也可以是连续的 二分类 先从用蓝色圆形数据定义为类型1&#xff0c;其余数据为类型2&#xff1b;只需要分类1次&#x…

ElasticSearch分词器和相关性详解

目录 ES分词器详解 基本概念 分词发生时期 分词器的组成 切词器&#xff1a;Tokenizer 词项过滤器&#xff1a;Token Filter 停用词 同义词 字符过滤器&#xff1a;Character Filter HTML 标签过滤器&#xff1a;HTML Strip Character Filter 字符映射过滤器&#x…

【Linux技术宝典】深入理解Linux基本指令:命令行新手指南

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅Linux技术宝典 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、Linux下基本指令1. ls 指令2. pwd指令3. clear指令4. cd指令什么是家目录&#xf…

2023全球云计算市场份额排名

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 最近Synergy研究院发布了最新的全球云计算市场份额排名。 亚马逊依旧是以31%的的市场份额排名第一&#xff0c;微软azure24%排名第二&#xff0c;Google云11%排名第三&#xff0c;阿里云4%排名第四。腾讯云和IBM、…

thinkphp5.0提示不支持redis,not support: redis

安装PHP扩展 例如宝塔&#xff0c;其他环境请用命令行&#xff0c;安装 redis配置完成以后&#xff0c;修改php.ini把redis扩展打开即可&#xff0c;重启环境

docker磁盘不足!已解决~

目录 &#x1f35f;1.查看docker镜像目录 &#x1f9c2;2.停止docker服务 &#x1f953;3.创建新的目录 &#x1f32d;4.迁移目录 &#x1f37f;5.编辑迁移的目录 &#x1f95e;6.重新加载docker &#x1f354;7.检擦docker新目录 &#x1f373;8.删掉旧目录 1.查看doc…

MySQL 基础知识(五)之数据增删改

目录 1 插入数据 2 删除数据 3 更改数据 创建 goods 表 drop table if exists goods; create table goods ( id int(10) primary key auto_increment, name varchar(14) unique, stockdate date )charsetutf8; 1 插入数据 当要插入的数据为日期/时间类型时&#xff0c;如果…

Mysql的安装、使用、优势与教程

一.安装 1.在小皮的设置界面检测3306端口&#xff0c;保障3306端口可用&#xff1b; 2、在小皮的首面界面&#xff0c;启动MySQL&#xff1b; 3、进行环境变量设置&#xff0c;找到MySQL的路径&#xff0c;进行复制&#xff1b; 4、在Windows的搜索栏内&#xff0c;输入“环境…

Vue2学习第一天

Vue2 学习第一天 1. 什么是 vue? Vue 是一套用于构建用户界面的渐进式框架。 2. vue 历史 vue 是在 2013 年创建的&#xff0c;vue3 是 2020 出现的&#xff0c;现在主要是用 vue2&#xff0c;创新公司用的是 vue3 vue 的作者是尤雨溪&#xff0c;vue 的搜索热度比 react…

【算法设计与分析】反转链表 ||

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表…

《UE5_C++多人TPS完整教程》学习笔记16 ——《P17 菜单类(The Menu Class)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P17 菜单类&#xff08;The Menu Class&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译者&#x…