【C语言】内存操作篇---动态内存管理----malloc,realloc,calloc和free的用法【图文详解】

news2024/12/23 23:09:09

欢迎来CILMY23的博客喔,本篇为【C语言】内存操作篇---动态内存管理----malloc,realloc,calloc和free的用法【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注+收藏。

前言

 在学完结构体后(结构体1:http://t.csdnimg.cn/ZkBHj结构体2:http://t.csdnimg.cn/rmAwJ)我们要进入新篇章了,内存操作中最关键的一节---动态内存管理,本篇博客将了解malloc,realloc,calloc和free的用法。

目录

一、为什么会有动态内存管理?

二、malloc和free

malloc的介绍和使用  

空间回收 

free的介绍和使用

三、realloc

realloc的介绍和使用 

四、calloc 

calloc的介绍和使用 


一、为什么会有动态内存管理?

 在过去我们向内存中申请空间有两种方式,一是创建变量,二是创建数组

#include<stdio.h>

int main()
{
	int C = 23;//申请四个字节空间
	char c = 'C';//申请1个字节空间
	char CI[10] = "CILMY23";//申请10个字节空间
	return 0;
}

但是上述的开辟空间的方式有两个特点:
•    空间开辟大小是固定的。
•    数组在声明的时候,必须指定数组的长度,数组空间一旦确定了大小不能调整
我们申请的空间都很固定,没法灵活调整,但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组和变量的编译时开辟空间的方式就不能满足了。
C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,就比较灵活了。 

二、malloc和free

malloc可以在cplusplus网站查询:malloc - C++ Reference (cplusplus.com)  

 malloc函数原型如下:

void* malloc (size_t size);

 malloc的函数介绍如下:

malloc 的功能如下:

malloc的介绍和使用  

malloc函数是头文件stdlib中的,malloc函数是用来向内存申请空间的(在堆区申请),在函数原型中我们可以看到有一个形参size_t size,根据Allocates a block of size bytes of memory, returning a pointer to the beginning of the block,我们知道这个形参是计算空间大小后得出的结果,比如申请40个字节空间,size就等于40.那它最后会返回一个指针,指向这个空间的起始位置,那返回类型是void*,因为我并不知道这段空间会干什么,所以返回void*(不懂可以看http://t.csdnimg.cn/dshm8),当malloc失败后,会返回一个NULL。

使用如下:

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

int main()
{
	// 向内存空间申请40个字节
	//将void*转换成int*类型将其存入指针变量p
	int* p = (int *)malloc(10 * sizeof(int));

	int i = 0;
	//将i存入开辟的空间
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//将空间中的数值打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
}

结果如下:

 

 图解如下:

 那如果我们申请失败了呢?那我们就可以用perror来直接打印错误信息。

if (*p == NULL)
{
	perror("malloc");
}

空间回收 

malloc是在堆区申请空间的,malloc的空间回收有两种方法,一是free回收,二是程序结束的时候,由操作系统回收 我们这里主要讲free回收,首先回顾一下内存的区域,主要由堆区栈区和静态区构成,堆区是动态分配区,像malloc这些,栈区是临时的参数,局部变量和形式参数,静态区主要是全局变量和静态变量。

 
     

free的介绍和使用

free函数的原型如下:

void free (void* ptr);

free函数介绍如下:

 free的功能和使用案例如下:

free函数是用来释放动态开辟出来的空间,给到地址就能释放地址所指向的位置 

free的使用:

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

int main()
{
	// 向内存空间申请40个字节
	//将void*转换成int*类型将其存入指针变量p
	int* p = (int *)malloc(10 * sizeof(int));

	if (*p == NULL)
	{
		perror("malloc");
	}
	int i = 0;
	//将i存入开辟的空间
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//将空间中的数值打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	free(p);
	p = NULL;
}

我们使用free(),因为我们将p所指向的空间释放了,那p就成了野指针,我们就需要处理野指针,所以将p置空。 

总结:

malloc如果开辟成功,则返回⼀个指向开辟好空间的指针。
•    如果开辟失败,则返回⼀个NULL 指针,因此malloc的返回值⼀定要做检查。
•    返回值的类型是void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
•    如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

free函数只能用来释放动态开辟的内存。
• 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
• 如果参数 ptr 是NULL指针,则函数什么事都不做。

三、realloc

 

 realloc函数可以在cplusplus网站查询:realloc - C++ Reference (cplusplus.com)

realloc的原型如下:

void* realloc (void* ptr, size_t size);

realloc的函数介绍如下:  

realloc的功能和使用案例如下: 

realloc的介绍和使用 

 realloc的参数有void* ptr, size_t size,size就是要调整后的空间大小,ptr则是要调整的空间起始地址。realloc 的调整分两种情况,一种是原地扩,也就是后面的空间足够,如下图所示,未分配的空间加已分配的橙色空间刚好够size,或者小于size,则realloc原地扩

第二种情况是未分配的黑色空间加已分配的橙色空间,超过size后的字节,那realloc会到新的一块未分配区域重新开辟一块空间,来分配原先的字节,并将原来的地址做拷贝,最后返回新的空间地址,并且旧空间会自动释放掉。

realloc的使用:

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

int main()
{
	int* p = (int*)malloc(10 * sizeof(int));

	int i = 0;

	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	//调整申请的堆上内存
	int* tmp = (int*)realloc(p, 40);
	if (tmp != NULL)
	{
		p = tmp;
		tmp = NULL;
	}
	else
	{
		perror("realloc");
	}

	free(p);
	p = NULL;

	return 0;
}

总结:

• ptr 是要调整的内存地址
• size 调整之后新大小
• 返回值为调整之后的内存起始位置。
• 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。
•    realloc在调整内存空间的是存在两种情况:
◦ 情况1:原有空间之后有足够大的空间
◦ 情况2:原有空间之后没有足够大的空间

四、calloc 

calloc函数可以在cplusplus网站查询:calloc - C++ Reference (cplusplus.com) 

calloc的原型如下:

void* calloc (size_t num, size_t size);

calloc的函数介绍如下: 

 

calloc的功能和使用案例如下: 

 

calloc的介绍和使用 

calloc的参数是两个,一个是num,一个是大小size,其中一个给数量,一个给大小。calloc和malloc函数最大区别就是,calloc会赋一个初值,每个初值都是0. 使用和malloc是差不多的

 

使用如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10 ,sizeof(int) );

	int i = 0;

	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}

	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}

	free(p);
	p = NULL;
}

 结果如下:

 

 如果我们只是想开辟空间,我们只需要用malloc,而calloc是把开辟出来的空间赋了一个初值。

总结:

•  函数的功能是为num 个大小为size的元素开辟⼀块空间,并且把空间的每个字节初始化为0
•  与函数malloc 的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全 0

感谢各位同伴的支持,本期动态内存管理篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。    

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

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

相关文章

《Trustzone/TEE/安全-实践版》介绍

第一章&#xff1a;课程说明和准备 课程介绍和说明 资料准备 为什么使用qemu_v8环境&#xff1f; 为什么选择香橙派开发板&#xff1f; optee qemu_v8环境展示 香橙派optee环境展示 第二章&#xff1a;Qemu环境搭建 ubuntu20.04的安装(virtualboxubuntu20.04) 搭建optee qem…

云手机的境外舆情监控应用——助力品牌公关

在当今数字化时代&#xff0c;社交媒体已成为品牌传播和互动的主要平台。随之而来的是海量的信息涌入&#xff0c;品牌需要及时了解并应对海外社交媒体上的舆情变化。本文将介绍如何通过云手机进行境外舆情监控&#xff0c;更好地帮助企业公关及时作出决策。 1. 境外舆情监控与…

BUUCTF---[BJDCTF2020]藏藏藏1

1.题目描述 2.下载附件&#xff0c;解压之后是一张图片和一个文本 3.把图片放在winhex,发现图片里面包含压缩包 4.在kali中使用binwalk查看&#xff0c;然后使用foremost分离&#xff0c;在使用tree查看分离出来的文件&#xff0c;最后将zip文件使用unzip进行解压。步骤如下 5.…

rtt的io设备框架面向对象学习-电阻屏LCD设备

目录 1.8080通信的电阻屏LCD设备1.1 构造流程1.2 使用2.i2c和spi通信的电阻屏LCD 电阻屏LCD通信接口有支持I2c、SPI和8080通信接口的。 1.8080通信的电阻屏LCD设备 rtt没有实现的设备驱动框架层&#xff0c;那么是在驱动层直接实现的&#xff0c;以stm32f407-atk-explorer为例…

NOIP 2010普及组初赛试题及解析

NOIP 2010普及组初赛试题及解析 一. 单项选择题 &#xff08;共20题&#xff0c;每题1.5分&#xff0c;共计30分。每题有且仅有一个正确答案.&#xff09;。二. 问题求解&#xff08;共2题&#xff0c;每题5分&#xff0c;共计10分&#xff09;三. 阅读程序写结果&#xff08;共…

SpringBoot-首页和图标定制

1.静态资源导入 SpringBoot中的静态资源&#xff0c;默认有以下四个路径可以访问&#xff1a; classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/ 其中第一个路径&#xff0c;一般不常用&#xff0c;它是来获取用maven导入webj…

[LeetBook]【学习日记】寻找链表相交节点

来源于「Krahets」的《图解算法数据结构》 https://leetcode.cn/leetbook/detail/illustration-of-algorithm/ 本题与主站 160 题相同&#xff1a;https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ 训练计划 V 某教练同时带教两位学员&#xff0c;分别以…

xshell安装java/jdk

1.下载jdk wget https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz 2.解压jdk安装包 tar -zxvf openjdk-11.0.1_linux-x64_bin.tar.gz 其中第三步 编辑 ~/.bashrc 或 ~/.bash_profile 文件 打开vim文本编辑器 vim ~/.bash_profile export …

基于springboot+vue的校园网上店铺

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

使用“弹性盒布局和媒体查询”实现一个响应式布局

要求实现如下布局&#xff1a; 当屏幕宽度大于640时 显示如下 当屏幕宽度小于640时 显示如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…

后端传给前端的时间字段前端显示不正确

具体问题是什么呢&#xff0c;就比如我后段有一个字段是TimeStamp类型&#xff0c;从数据库中查出数据是下面的样式&#xff1a; 但是前端显示的是下面的格式&#xff1a; 这个的解决方法还是挺多的&#xff0c;那接下来具体来看看吧~ 第一种&#xff1a; 在application.prop…

DataWorks(ODPS)性能优化技巧指南

使用阿里云DataWorks进行数据处理的时候&#xff0c;有时候会遇到一个sql或pyodps&#xff08;本质上还是转化为sql&#xff09;执行很长的情况&#xff0c;这个时候有必要对代码进行性能优化。 一、打开ODPS运行评估报告 一个sql脚本执行完毕后&#xff0c;在运维中心的周期…

Untiy 使用AVProVideo插件获取视频的长度

AVPro Video是Unity中一个非常流行的视频插件&#xff0c;可在Unity项目中实现高性能的视频播放功能&#xff0c;功能强大且易用。 如图所示&#xff0c;如果我要获取该视频的长度&#xff0c;方法是很简单的。 1、创建一个测试脚本&#xff1a; using RenderHeads.Media.AVP…

Python知识汇总

重要链接&#xff1a; matplotlib库&#xff1a;matplotlib — Matplotlib 3.5.1 documentation DataFrame库&#xff1a;DataFrame — pandas 2.2.1 documentation (pydata.org) Python Matplotlib 实现散点图、曲线图、箱状图、柱状图示例&#xff1a;Python Matplotlib 实…

Python爬虫实战!爬取百度指数并可视化

大家好&#xff0c;我是小F&#xff5e; 这两年AI可以说是非常火&#xff0c;尤其是AIGC领域。 而这其中很多都是基于Python实现的&#xff0c;比如ChatGPT、AI绘画、声音克隆等等。 对于普通人来说&#xff0c;想直接学习这些高难度的Python项目&#xff0c;还是比较困难的。 …

Elixir 依赖 (deps) 调试的小技巧

最近使用 Elixir 有点多, 经常需要观察一些依赖 (Deps) 的实现, 比如想加个日志打印点 IO.inspect 啥的观察下某个变量&#xff0c;才能更好的理解某个 Elixir 的依赖。这里介绍下一些调试的方式: 这里以 yeshan333/ex_integration_coveralls 为例子. 我们先 clone 项目到本地…

Matlab 机器人工具箱 符合动力学

文章目录 1 符合化表示1.1 标准DH动力学1.2 改进DH动力学 质量集中在质心1.2 改进DH动力学 质量集中在末端1.3 程序问题1.3.1 Unable to perform assignment because value of type sym is not convertible to double.1.3.2 CAT arguments dimensions not consistent.参考链接1…

测试用例设计指南

软件测试设计是测试过程中重要的测试活动&#xff0c;怎么样设计测试用例能提高我们测试的效率和质量&#xff0c;从以下几个方面做了简单的讲解。 1、测试用例设计原则 测试用例设计的基本原则包括&#xff1a;有效性、清晰性、可复用性、可维护性、完整性、兼容性、易操作性…

JS利用Worker多线程大文件切片上传

在做前端上传时&#xff0c;会遇到上传大文件&#xff0c;大文件就要进行分片上传&#xff0c;我们整理下思路&#xff0c;实现一个分片上传&#xff0c;最终我们要拿到每一个分片的hash值&#xff0c;index 分片索引&#xff0c;以及分片blob&#xff0c;如下&#xff1a; 一…

递归学习资料

思路 例题 package 递归;public class 反向打印字符串 {public static void main(String[] args) {f("ABC",0);}static void f(String str,int n){if (nstr.length()){return;}f(str,n1);System.out.println(str.charAt(n)"");} }多路递归 递归优化 -剪枝…