C/C++程序内存区域划分以及各区域的介绍

news2024/11/25 1:06:35

C/C++程序内存区域划分

直接上图:

在这里插入图片描述

注:以下的说明均已VS2019为例

栈区(stack)

在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元会自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存空间有限。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等

在栈空间存储数据时地址的变化

栈空间遵循“先入后出”原则。

栈区的数据是从高地址向低地址存储的,最新压入栈的数据位于栈底(高地址),而最早压入栈的数据位于栈顶(低地址)。

我们以一个具体的例子来进行说明:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	char a = 10;
	char b = 10;

	printf("%p\n", &a);
	printf("%p\n", &b);

	return 0;
}

output

008FFA3B
008FFA2F
  • 局部变量a先于变量b存入栈区,因此a的地址要高于b的地址

在栈空间读取数据时地址的变化

当读取栈区的数据时,是从低地址向高地址访问,也就是从栈顶向栈底读取数据。

首先我们要明白,在VS2019中,栈区中的数据是以小端字节序存储的,还不清楚的小伙伴看这里👉整数在内存中的存储

我们以一个具体的例子来进行说明:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int num = 0x11223344;
	char* pc = &num;
    
	printf("%x\n", *pc);

	return 0;
}

output

44
  • int型num占4个字节,由于采用小端存储,低位数据44要放在低地址:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5L80Hfd6-1689750718686)(C:\Users\HUASHUO\AppData\Roaming\Typora\typora-user-images\image-20230715102005060.png)]

  • 而由于栈区的数据是由低地址向高地址访问,因此指针pc指向的应该是变量num的低位字节,管理一个字节,因此打印44

数组在栈区的存储

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int num1[5] = { 0 };
	for (int i = 0; i < 5; i++)
		printf("%p\n", &num1[i]);

	printf("\n");

	int num2[5] = { 0 };
	for (int i = 0; i < 5; i++)
		printf("%p\n", &num2[i]);
    
	return 0;
}

output:

0113FE08
0113FE0C
0113FE10
0113FE14
0113FE18

0113FDE0
0113FDE4
0113FDE8
0113FDEC
0113FDF0

可以画出示意图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KVfxM1O3-1689750718686)(C:\Users\HUASHUO\AppData\Roaming\Typora\typora-user-images\image-20230715103849782.png)]

可以得出结论:

随着下标的增长,数组元素的地址逐渐加大

堆区(heap)

堆区一般存储的是动态内存如由malloc,calloc,realloc动态开辟的空间。这些空间一般由程序员分配释放,若不释放,程序结束时可能由OS回收,但若程序没有结束,则会造成内存泄漏,因此动态开辟的空间一定要记得free释放。内存分配的方式类似于链表

在堆区存储数据时地址的变化

通常情况下,堆区的地址分配是从低地址到高地址进行的,即在堆区中分配的内存空间的地址是逐渐增大的。这是因为堆区是通过动态内存分配来实现的,通常使用链表或类似的数据结构来管理已分配和未分配的内存块。新分配的内存块会被添加到链表的末尾,因此地址是递增的。

例如:

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int* arr1 = (int*)malloc(sizeof(int) * 5);
	if (NULL == arr1)
	{
		perror("malloc");
		return 1;
	}

	int* arr2 = (int*)malloc(sizeof(int) * 5);
	if (NULL == arr2)
	{
		perror("malloc");
		return 1;
	}

	printf("%p\n",arr1);
    printf("%p\n",arr2);
    
	free(arr1);
	free(arr2);
	arr1 = NULL;
	arr2 = NULL;

	return 0;
}

output

00ED1E28
00ED1E68

可以看到后存入的数据地址更大

在堆区读取数据时地址的变化

在堆区中读取数据时,并没有固定的规定要求从高地址到低地址读取。可以通过指针来访问堆区中的数据,可以根据需要进行读取和修改操作,而不是受地址增长方向的限制。

数组在堆区的存储

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int* num1 = (int*)malloc(sizeof(int) * 5);
	if (NULL == num1)
	{
		perror("malloc");
		return 1;
	}
	for (int i = 0; i < 5; i++)
		printf("%p\n", &num1[i]);

	printf("\n");

	int* num2 = (int*)malloc(sizeof(int) * 5);
	if (NULL == num2)
	{
		perror("malloc");
		return 1;
	}
	for (int i = 0; i < 5; i++)
		printf("%p\n", &num2[i]);

	free(num1);
	free(num2);
	num1 = NULL;
	num2 = NULL;

	return 0;
}

output

00ED1E28
00ED1E2C
00ED1E30
00ED1E34
00ED1E38

00ED1E68
00ED1E6C
00ED1E70
00ED1E74
00ED1E78

可以画出示意图(注意比较和栈区的区别):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Iq0yxWvD-1689750718687)(C:\Users\HUASHUO\AppData\Roaming\Typora\typora-user-images\image-20230715110940508.png)]

数据段(静态区)

(static)存放全局变量、静态数据。程序结束后(不是函数结束)由系统释放

代码段

存放函数体(类成员函数和全局函数)的二进制代码以及只读常量。

关于数据的读取

在计算机系统中,数据的存储和读取通常是以字节为单位进行的。对于单个字节的数据,无论是在堆区、栈空间还是其他存储区域,数据的存储和读取都是从低位(低地址)向高位(高地址)进行的

在C语言中,数据类型的存储和读取也遵循这个原则。例如,对于整型数据类型(如int、long等),它们通常占用多个字节的内存空间,其中每个字节都按照从低位到高位的顺序存储数据。

当我们读取一个整型变量时,计算机会从最低有效字节开始,按照地址逐字节读取数据,然后根据数据类型的大小将其合并为一个完整的值。这种方式被称为"小端字节序"(Little-Endian),它是目前主流的处理器架构所采用的方式。

需要注意的是,在特定的硬件平台或编译器中,也可能存在"大端字节序"(Big-Endian)的方式。在大端字节序中,数据的存储和读取是从高位到低位进行的。但是,大端字节序相对较少见,小端字节序是C语言中的常见规范。

综上所述,一般情况下,在计算机系统中,数据的存储和读取是从低位向高位进行的,即从低地址到高地址进行。这是C语言和许多常见的计算机系统所采用的数据存储方式。

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

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

相关文章

用自己的数据拟合Sigmoid函数(Matlab平台)

%% 拟合sigmoid曲线 sigmoid (params, x) params(1) ./ (1 exp(-params(2) .* (x - params(3)))) params(4); %params(1) 是斜率参数&#xff0c;params(2) 是增长速率参数&#xff0c;params(3) 是 x 值的偏移参数&#xff0c;params(4) 是 y 值的偏移参数。 initialGuess…

剑指offer刷题笔记--Num51-60

1--数组中的逆序对&#xff08;51&#xff09; 主要思路&#xff1a; 基于归并排序&#xff0c;视频讲解参考&#xff1a;数组中的逆序对 #include <iostream> #include <vector>class Solution { public:int reversePairs(std::vector<int>& nums) {if(…

【力扣算法17】之 19. 删除链表的倒数第 N 个结点 python

文章目录 问题描述示例1示例2示例3提示 思路分析代码分析完整代码详细分析运行效果截图完结 问题描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例1 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例2…

加强安全防护,提升日志管理——探索EventLog Analyzer

导言&#xff1a; 在当今数字化时代&#xff0c;安全威胁和数据泄露已经成为各个组织和企业面临的严峻挑战。有效的日志管理和监控是确保网络安全的重要一环。本文将介绍EventLog Analyzer&#xff08;事件日志分析器&#xff09;这一强大工具&#xff0c;探索其在日志安全方面…

五、DQL-2.基本查询

一、数据准备 1、删除表employee&#xff1a; drop table employee; 2、创建表emp&#xff1a; 3、添加数据&#xff1a; 4、查看表数据&#xff1a; 【代码】 -- 查询数据--------------------------------------------------------- drop table emp;-- 数据准备-----------…

uni-app image加载错误 404 替换为默认图片

双层v-for 使用item修改 aitem.cat_icon || defaultPic绑定图片src属性为aitem.cat_icon 如果aitem.cat_icon的值为空字符串或undefined&#xff0c;那么默认图片defaultPic被显示出来当图片加载错误时,触发handleImageError方法,将aitem传进去 <!-- 页面--><view …

windows下mysql8定时备份,bat脚本编写,dos免密执行

前提&#xff1a;mysql8已经安装。 编写脚本copy_mysql_data.bat echo off set timestamp%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2% set backupfileD:\ProgramData\MySQL\Backup\backup_%timestamp%.sql set mysqlpathD:\Program Files\MySQL\MyS…

成为一个年薪30W+的DFT工程师是一种什么体验?

一直以来&#xff0c;DFT都是数字IC设计行业中相对神秘的一个岗位。 你说他重要吧&#xff0c;并不是所有芯片设计公司都有这个岗位&#xff0c;你说他不重要吧&#xff0c;但凡芯片产品达到一定规模后&#xff0c;就必须设置DFT部门。 一、什么是DFT&#xff1f; DFT&#x…

1haclon 简单操作

文章目录 *读取图片 read_image(Image,claudia) *转换为灰度 rgb1_to_gray(Image,GrayImage)阈值分割 区域连接 获取最衣服 *读取图片 read_image(Image,claudia) *转换为灰度 select_shape (Connection, SelectedRegions, area, and, 40963.3, 44724.8) rgb1_to_gray(Image,Gr…

AI绘画 | 迷人武士美少女战士作品集

今天用Midjourney生成了质量极高的美少女武士后续会作为固定栏目来分享美图接下来请欣赏作品 提示词分享&#xff1a;1.an asian girl dressed in samurai style, in the style of anime aesthetic, trick of the eye paintings, dollcore, light red and black, resin, 8k, ex…

教程 | 如何10秒内一键生成高质量PPT

Hi! 大家好&#xff0c;我是赤辰&#xff01; 近期新进的学员不少职场小白&#xff0c;对AI工具提效办公很感兴趣&#xff0c;今天火速给大家安排&#xff0c;ChatGPTMindShow强强联合&#xff0c;30秒内快速生成PPT&#xff0c;对于策划小白来说简直是福音呀&#xff01; 市…

Java 多文件压缩与解压

1&#xff0c;写多个文件到压缩包 import org.apache.tools.zip.ZipEntry;import org.apache.tools.zip.ZipFile;import org.apache.tools.zip.ZipOutputStream;public static void main(String[] args) {//压缩文件对象String zipPath "D:\\download\\files0719.zip&quo…

15 大模型训练 内存优化

先看GPU结构&#xff0c;我们常说显存的时候&#xff0c;说的一般就是Global memory 训练的过程中&#xff0c;我们为了反向传播过程&#xff0c;必须将中间的结果&#xff08;激活值&#xff09;存储下来。 在训练的过程中&#xff0c;那些会消耗内存呢&#xff1f; model we…

ubuntu20.04系统安装使用labelme标注数据集

一、Anaconda的安装 请参考&#xff1a;MediapipeVSCodeAnaconda 实时检测手部关键点并保存视频_苦瓜汤补钙的博客-CSDN博客 二、Labelme的安装 1.打开终端创建虚拟环境 # 创建labelme的环境 conda create -n labelme python3.9 输入“y”&#xff0c;然后回车。 2.激活虚拟…

为什么媒体和创意工作者更喜欢 Splashtop 进行远程访问

在当今快速发展的数字环境中&#xff0c;可靠的远程访问已成为全球媒体和创意工作者不可或缺的工具。 远程访问让创意工作者不再受传统办公空间边界的限制&#xff0c;完全实现了随时随地办公。无论是实时剪辑、高分辨率渲染还是其他创意任务&#xff0c;创意工作者对高性能远…

Go语言之包管理

1、package Go语言是使用包来组织源代码的&#xff0c;包&#xff08;package&#xff09;是多个 Go 源码的集合&#xff0c;是一种高级的代码复用方案。Go语言中为我们提供了很多内置包&#xff0c;如 fmt、os、io 等。任何源代码文件必须属于某个包&#xff0c;同时源码文件的…

新书发布!《数字化时代研发效能跃升方法与实践》作者序丨IDCF

作者团队&#xff1a; 姚冬、王立杰、徐磊、许舟平 为什么会有本书 只是因为在人群之中&#xff0c;多看了你一眼。这一切&#xff0c;都要从IDCF的发端讲起 缘起IDCF 时间如白马过隙&#xff0c;我们成立IDCF一晃已有四年&#xff0c;而距离上一本书《敏捷无敌之DevOps时…

基于FME二开产品:NewGIS integration介绍

目录 前言 一、模板上传 二、模板在线运行 1.模板参数解析 2.模板运行 三、成果管理 总结 前言 爆肝两个月&#xff0c;我和我的团队终于打造出了一款能完美适配所有FME模板的在线模板管理平台&#xff0c;目前支持FME2021版本的所有模板的在线运行、管理。整体技术框架…

C++基础算法排序篇

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C算法 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要讲解C算法中所涉及到的两个排序算法&#xff0c;快排和归并。 文章…

请问支付功能如何测试

目录 01测试思维 02支付功能的测试点 一&#xff1a;支付的分类&#xff1a; 二&#xff1a;功能测试 三&#xff1a;接口测试 四&#xff1a;安全测试 五&#xff1a;测试点 01测试思维 要分析测试点之前&#xff0c;我们先来梳理一下测试思维。总结来说&#xff0c;任…