c语言进阶指南(17)——动态内存管理

news2024/11/24 11:14:41

欢迎来到博主的专栏——c语言进阶指南
博主id已更新:

文章目录

    • 动态内存分配
    • malloc
    • 动态内存的释放
    • free
    • 其他的动态内存管理函数
    • calloc
    • realloc
      • 使用realloc函数调整动态内存空间
      • 使用realloc函数分配动态内存空间

动态内存分配

动态内存分配是内存分配的一种方法,与此相对的是静态内存分配,在前面我们已经知道了在创建如下变量时,系统会为变量划分一个内存区域

int i;//四个字节的空间
char c;//一个字节的空间
int arr[10];//四十个字节的空间
int *pi;//4/8字节的空间

这些变量的存储形式有以下特点:
(1)这些变量的大小由声明的类型决定的。
(2)这些变量的生命周期取决于创造这个变量的区域,关键字,而非程序。
(3)这些变量的大小在运行过程中不会改变。

如果C语言只有这种特点的变量的话,能实现的操作会受到限制。

比如在创建一个班级的目录时,A班今年有38人,我创建的数组是38个元素,明年A班来了两个转学生,那么是不是又要将整个程序修改一遍呢?当然可以设计一个100元素的数组,但是这又会造成内存浪费了,总之静态内存的管理虽然简单,但是在实现一些操作上会带来一些影响

为了让一些操作变得更加灵活,使用动态内存可以让程序员对自己的程序更加掌握,动态内存的大小由程序决定,生命周期也由程序决定,在程序运行的过程中还能对内存区域进行操作。我们先来了解一下动态内存分配的函数

malloc

malloc的函数原型如下:
在这里插入图片描述

(1)size是一个size_t类型的参数,意思是此次需要开辟的空间,单位字节。
(2)malloc函数会开辟size个字节的空间,这些空间是连续的,随机的,开辟成功后会返回这个空间的起始地址
(3)如果开辟失败,返回空指针

malloc(4);

在这里插入图片描述

可以看到这个空间是一个四个字节的空间,这个空间是没有数据类型,或者说这个空间是作为什么类型的数据来使用是由程序员决定的,可以将其当做一个int类型的数据,也可以用作一个char类型,由4个元素组成的数组

malloc函数开辟的空间是随机的,所以这个空间的起始地址也是随机的,一个随机的地址我们是难以直接使用的,应该使用一个指针指向这个空间来方便访问这个空间.

如果想要把这个空间当成int类型的数据来使用,可以用int*类型的指针来指向。

int *p;
p=malloc(4);
*p=0x11223344;

那么这段空间的数据就会变成(小端环境下)

在这里插入图片描述

如果想要当成char类型的数组来转换,可以用char*类型的指针来指向

char* p;
p = malloc(4);
*(p) = 'a';
*(p + 1) = 'b';
*(p + 2) = 'c';
*(p + 3) = '\0';

在这里插入图片描述

前面提到过这个函数的返回值是一个void类型的指针,所以我们可以在这个过程加上类型转换(不加也没有影响)

int *p=(int*)malloc(4);

开辟的空间用作数组时,要注意p是保持指向起始地址的(这对内存的释放很重要),在指针章节中我们曾通过移动指针来实现对数组进行赋值。

int* p = malloc(sizeof(int) * 10);//在内存中申请一个10个int类型的变量的连续空间
for (int i = 0; i < 10; i++)
{
	*p++=i;//由于指针自加,导致指针的指向发生移动,这个指针p不再指向起始地址
}

但是动态内存的指针一定要尽可能的指向起始地址,所以得换个方法来赋值,这里给上常用的两种方法
(1)再创建一个指针,让这个指针来移动实现赋值
(2)不移动指针,让指针通过加减的算术运算指向需要操作的地址(推荐)
这里写出第二种方法下的赋值操作

int main()
{
	int* p = malloc(sizeof(int) * 10);//在内存中申请一个10个int类型的变量的连续空间
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i;//p没有被移动,而是通过算术来定位。
	}
}

动态内存的释放

局部变量的作用域是有一定范围的,当程序运行超过这个范围时,内存会自动释放。这个变量也就不能再使用了。

而动态内存的释放则不一样,前面已经提到了动态内存是更加灵活的内存分配形式,内存释放的节点是由程序员决定的。而动态内存的释放需要用到一个free函数

free

free的函数原型如下:
在这里插入图片描述

(1) free函数的参数是一个viod*的指针,参数需要是指向一个动态开辟的内存空间的起始地址的指针
(2)free没有返回值

free函数的作用是将这个起始地址的动态内存给释放掉,使用free函数要注意以下几点

(1)free函数的指针一定要指向一个动态开辟好的空间,如果这个指针指向的空间不是动态开辟的内存空间,会造成未定义的结果

未定义的结果:由于c标准中没有定义这个行为会造成什么结果,所以这个代码产生的效果由编译器决定(即不同的编译可能会导致不同的结果)

以vs2022为例

int a = 0;
int* pa = &a;
free(pa);

在这里插入图片描述
可以发现在执行这段代码时vs2022会报错

执行一个未定义的行为会导致未知的结果,所以对于每一个未定义的行为都应该不去使用,即使这个行为会造成正向结果,因为这个代码是不具有可移植性的(不同的编译器会有不同的结果)。而且更严重的后果可能是整个项目的崩溃

(2)free函数参数的指针,必须指向一个动态内存开辟的空间的起始地址,如果在程序的过程中指针发生移动,使得这个指针指向的空间是动态开辟的内存空间,但指针不再指向空间的起始地址,这个使用方式也是错误的

int* p = malloc(40);
for (int i = 0; i < 3; i++)
{
	*p++ = i;
}
free(p);

在这里插入图片描述可以发现,即使执行程序后的p指向的仍是动态内存空间,但不再是空间的起始地址,那么这个程序就是错误的。

尝试运行可以发现编译器报错
在这里插入图片描述

其他的动态内存管理函数

calloc

calloc函数的函数原型如下:
在这里插入图片描述
calloc函数的作用与malloc的作用类似,都是通过参数开辟一定的动态内存空间,但是calloc在函数的参数上与malloc不同。
在这里插入图片描述

其中num是此次开辟的元素个数
size是一个元素占用的大小,单位字节

也就是说如果想要开辟40字节的空间,那么程序应该这么写

malloc(40;
calloc(4,10);

除此之外calloc肯定会有与malloc不同的作用,不然这个函数就没有存在的意义。

calloc函数开辟的动态空间是初始化好的空间,而malloc函数开辟的空间是未初始化的,在vs2022的内存监视窗口中可以看出
在这里插入图片描述
这是malloc函数开辟的空间,其中cd说明这片数据还没有被初始化。
在这里插入图片描述
这是calloc开辟的内存空间,可以发现这些数据都被初始化成了0.

并非所有的编译器都有这么直观的窗口,我们也可以使用这段代码来发现这两个函数的区别。

int main()
{
	int* ptr1 = malloc(40);
	int* ptr2 = calloc(4, 10);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%x ", *(ptr1+i));
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("%x ", *(ptr2+i));
	}
	free(ptr1);
	free(ptr2);
	return 0;
}

在这里插入图片描述
从代码的运行结果可以看出,malloc函数不会对开辟的内存区域的数据进行初始化,而calloc会将其初始化成0.

realloc

前面只提到了动态内存的分配和释放,但是动态内存还有一个关键的作用就是可以在运行的过程中调节这段内存空间的大小。这里介绍动态内存重分配函数realloc。

先来看看realloc函数的函数原型

在这里插入图片描述

memblock是一个void的指针,这个参数是需要重新分配的空间的指针
size是新空间的大小
realloc函数的返回值是一个void
的指针,这个指针是指向新开辟的空间的起始地址的指针
开辟失败则返回NULL。

使用realloc函数调整动态内存空间

如果将一个函数的第一个参数,是指向动态内存的空间的起始地址的指针,那么这个函数的作用,就是将这个指针指向的动态内存的空间进行大小调整

	int* p = malloc(40);
	int* ptr = realloc(p, 80);

上述代码的作用是将p指向的那段动态内存的空间,从40字节的大小,变为80字节的大小。
也可以用这个函数将内存空间变小

	int* p = malloc(40);
	int* ptr = realloc(p, 20);

此时p指向的这段动态内存的空间由40字节变为20字节,而且这个多余的20字节的空间会被直接释放掉。

使用realloc函数分配动态内存空间

如果realloc函数的第一个参数是NULL,那么此时这个函数会随机分配一个大小合适的动态内存空间给你。这和malloc的作用是一致的

malloc(40);
realloc(NULL,40);

此时这两个函数的作用没有区别。

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

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

相关文章

android 实时流媒体 实时流媒体播放

场景描述 将实时流采集终端的视频数据实时推送到另外一个&#xff08;多个&#xff09;播放终端&#xff0c;完成远距离实时视频播放的功能。典型场景&#xff1a; &#xff08;1&#xff09;远程查看监控摄像头。选择指定摄像头&#xff0c;将该摄像头采集到的实时数据推送到…

学习华为企业无线网络,有这篇文章就够了(二)

学习华为企业无线网络&#xff0c;有这篇文章就够了&#xff08;一&#xff09;https://xmws-it.blog.csdn.net/article/details/135385614 WLAN的基础配置命令 - 配置AP上线 (1) •命令&#xff1a;optioncode [ sub-optionsub-code ] { asciiascii-string | hex hex-string |…

ChatGPT新出Team号 年付费

之前一直传的团队版ChatGPT终于来了&#xff0c;这个对拼单的比较合算。每人每月25美元&#xff0c;只能按年支付。 团队版比普通版多的权益有&#xff1a; ◈更多的GPT-4消息上限&#xff0c;三小时100次。 ◈可以创建与团队内部共享的GPTs。 ◈用于工作空间管理的管理员控…

数字化转型助力保险业腾飞,国产化安全产品护航高质量发展

近几年&#xff0c;全球贸易和经济受到了巨大冲击&#xff0c;众多贸易企业经营环境面临困难&#xff0c;某保险公司为国内企业提供强有力的保险保障&#xff0c;大大减轻了企业在国际贸易中风险&#xff0c;为国家经济恢复起到关键的作用。2022年&#xff0c;该保险公司承保金…

大数据 - Doris系列《三》- 数据表设计之表的基本概念

目录 &#x1f436;3.1 字段类型 &#x1f436;3.2 表的基本概念 3.2.1 Row & Column 3.2.2 分区与分桶 &#x1f959;3.2.2.1 Partition 1. Range 分区 2. List 分区 进阶&#xff1a;复合分区与单分区的选择 3.2.3 PROPERTIES &#x1f959;3.2.3.1 分片副本数 &#x1f…

聚丙烯PP它的化学特性是什么? UV胶水能够粘接聚丙烯PP吗?

聚丙烯&#xff08;Polypropylene&#xff0c;简称PP&#xff09;是一种热塑性聚合物&#xff0c;属于聚烯烃类塑料之一。以下是聚丙烯的一些化学特性&#xff1a; 1. 分子结构&#xff1a; 聚丙烯是由丙烯单体&#xff08;propylene&#xff09;聚合而成的。其分子结构主要由…

235个国家-数字经济发展相关23个指标(2000-2022年)

本文涉及235个国家的数字经济发展的23个相关指标数据&#xff0c;为我们提供了一个全面的视角&#xff0c;用以分析和比较全球范围内数字经济的发展状况。这些国家&#xff0c;年份&#xff0c;移动网络覆盖率&#xff0c;固定电话普及率&#xff0c;固定宽带普及率等指标。这些…

【Web】CTFSHOW PHP命令执行刷题记录(全)

目录 web29 web30 web31 web32 web33 web34 web35 web36 web37-39 web40 web41 &#xff08;y4✌脚本&#xff09; web42 -44 web45 web46 -49 web50 web51 web52 web53 web54 web55-56 web57 web58 web59 web60 web61 web62 web63-65 web66-67 w…

十个月,双非从零到大厂实习,我经历了什么?

个人背景 「双非大三」计科专业在读&#xff0c;某短视频「一线大厂」数据开发 22年10月份接触大数据&#xff0c;次年4月开始收割小厂实习offer&#xff0c;七月进入小厂实习&#xff0c;八月通过大厂面试 我只是万千普通人中的幸运儿&#xff0c;希望我的经历可以给一些人…

vulhub中的Nginx 文件名逻辑漏洞(CVE-2013-4547)

目录 Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09; 1.cd到CVE-2013-4547 2.执行docker-compose up -d 3.查看靶场是否开启成功 4.访问浏览器 5.上传含有一句话木马的图片 6.burp抓包 7.在shell.gif加空格 8.放包 9.访问路径 10.继续抓包 11.在aa后面…

基于Java开发的工作流审批系统,自定义工作流,表单绑定

前言 activiti工作流&#xff0c;企业erp、oa、hr、crm等审批系统轻松落地&#xff0c;请假审批demo从流程绘制到审批结束实例。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;快速开发平台&#xff0c;可插拔工作流服务。 二、项目介绍 本项目…

5、C语言:结构

结构 结构的基本知识结构与函数传递结构 结构数组、指向结构的指针自引用结构&#xff08;二叉树&#xff09;表查找类型定义&#xff08;typedef&#xff09;联合位字段 结构也是一种数据类型。类似于int、char、double、float等。 结构是一个或多个变量的集合&#xff0c;这些…

SG-8101CGA 系列 (晶体振荡器 可编程 可用 +125°C )

SG-8101CGA是可编程晶体振荡器&#xff0c;具有CMOS输出&#xff0c;适用于汽车&#xff0c;同时&#xff0c;该系列还提供相同的频率和其他参数的轻松编程能力&#xff0c;符合AEC-Q100标准&#xff0c;具有出色的电磁兼容性和稳定性&#xff0c;可以在各种环境下使用。外部尺…

判断质数-- 试除法判定质数(终于有人给我说明白了)

目录 判断质数思路&#xff1a;代码 原题链接 判断质数 给定 n个正整数 ai&#xff0c;判定每个数是否是质数。 输入格式 第一行包含整数 n 。 接下来 n 行&#xff0c;每行包含一个正整数 ai 。 输出格式 共 n 行&#xff0c;其中第 i 行输出第 i 个正整数 ai 是否为质数&…

社交距离 - 华为OD统一考试

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C++ 题目描述 疫情期间,需要大家保证一定的社交距离,公司组织开交流会议,座位有一排共N个座位,编号分别为[0…N-1],要求员工一个接着一个进入会议室,并且可以在任何时候离开会议室。 满足:每当一个员工进入时,…

虚拟主机 如何上传大于100M的文件 php网站程序

问题 虚拟主机上传文件大小限制100m&#xff0c; 有时会遇到非常大的文件上传&#xff0c;上传过程中耗时非常久&#xff0c; 可能服务器的限制设置了上传文件尺寸&#xff0c;返回“413 request entity too large” 整体逻辑 前端&#xff1a;上传文件时&#xff0c;进行文…

vue前端开发自学,组件的嵌套关系demo

vue前端开发自学,组件的嵌套关系demo!今天开始分享的&#xff0c;前端开发经常用到的&#xff0c;组件的嵌套关系案例代码。下面先给大家看看&#xff0c;代码执行效果。 如图&#xff0c;这个是代码执行后&#xff0c;的效果布局&#xff01; 下面给大家贴出来源码。方便大家…

C++_vector类

目录 一、vector的模拟实现 1、vector的组成结构 2、vector尾插数据 2.1 析构函数 3、迭代器实现 4、resize 5、删除数据 5.1 迭代器失效 6、指定位置插入数据 6.1 迭代器失效 7、迭代器构造和resize构造 8、深浅拷贝 结语&#xff1a; 前言&#xff1a; vect…

Vue3:使用解构赋值来读取对象里的键-值对(值也是对象)

一、前言 在Vue3中&#xff0c;想要读取一个对象的“键—值”对&#xff08;值也是一个对象&#xff09;&#xff0c;数据格式如下&#xff1a; {1:{courseName: 课程1, study: 951526, visit: 3785553}&#xff0c;2:{courseName: 课程2, study: 181630, visit: 380830}&…

Open CV 图像处理基础:(五)Java 使用 Open CV 的绘图函数

Java 使用 Open CV 的绘图函数 使用 Open CV 在 Java 中对图片使用绘图函数&#xff0c;分别绘制矩形、斜线、圆形、椭圆形以及添加文本 Java 使用 Open CV 的绘图函数 Java 使用 Open CV 的绘图函数函数绘制矩形绘制线绘制圆形绘制椭圆添加文本 代码示例 函数 绘制矩形 Im…