15. 《C语言》——【如何动态内存开辟】

news2024/11/20 3:20:29

在这里插入图片描述

亲爱的读者,大家好!我是一名正在学习编程的高校生。在这个博客里,我将和大家一起探讨编程技巧、分享实用工具,并交流学习心得。希望通过我的博客,你能学到有用的知识,提高自己的技能,成为一名优秀的程序员。如果你有任何疑问或建议,请随时在评论区留言,让我们一起成长进步!现在,让我们开始这场知识之旅吧!



🚀个人主页:FEN03
📚收入专栏:C语言

在这里插入图片描述



文章目录

  • 📚前言
  • 📘1. 为什么要动态内存分配❓
  • 📗2. 如何去动态内存开辟❓
    • 🔖2.1 malloc
    • 🔖2.2 free
    • 🔖2.3 calloc
    • 🔖2.4 realloc
  • 👋结束语


📚前言

为什么需要动态内存开辟,如何向内存申请空间?接下来,就让我们去探讨吧~


📘1. 为什么要动态内存分配❓


在先前,我们开辟内存的方法无非是在栈区创建一个变量,或者说一个数组。

#include<stdio.h>
int main()
{
	int a = 0; //在栈区开辟了4个字节的空间
	int arr[10] = { 0 }; //在栈区开辟了40个连续字节的空间
	return 0; 
}

这2种内存开辟,都存在着2种特点

  1. 内存开辟的大小是固定的了。
  2. 数组在创建时,必须是指定它的长度,一旦确定大小后不能再进行更改

为了迎合更高的要求,上述的情况就不能满足了。那么为了解决这一问题,C语言引入了动态内存开辟,这样程序员就可以灵活的去申请和释放空间。

那么接下来就让我们探索如何去动态的向内存开辟。


📗2. 如何去动态内存开辟❓

那么为了实现动态内存的开辟,C语言提供了4个函数,那么接下来,就让我们去学习如何使用这些函数吧~⬇️


🔖2.1 malloc

为了实现动态内存开辟,C语言提供了malloc函数。

函数语法形式:

void* malloc (size_t size);

这个函数能够向内存开辟一块连续可用的空间,并且会返回指向这块内存空间的指针。

  1. 如果内存开辟成功,则会返回指向这块开辟好的内存的指针。
  2. 如果内存开辟失败,则会返回NULL,所以当我们使用malloc函数时,一定要检查是否开辟成功。
  3. malloc函数的返回类型是void* ,这是因为malloc函数并不知道程序员要开辟内存空间的类型,所以当程序员使用时由自己决定返回类型。
  4. 如果size为0,这一行为是标准未定义的,而且也没必要,最终的结果也是编译器决定的。

使用malloc函数需要包含头文件:

#include<stdlib.h>

我们可以使用malloc来开辟下内存空间:


#include<stdio.h>
#include<stdlib.h>
int main()
{
	//向内存开辟40个字节
	int*p = (int*)malloc(10 * sizeof(int));  
	//使用if语句来判断是否开辟成功,如果失败则提示错误信息以及提前结束
	if (p == NULL)
	{
		perror("malloc"); 
		return 1; 
	}

	//...... 

	return 0; 
}

我们进行调试看看是否开辟成功?

在这里插入图片描述

我们看到已经内存开辟成功了,这些值都是cd,也就是一些随机值。

但是malloc只是这样使用吗,其实并不是,malloc是需要搭配free函数使用的。接下来,就让我们介绍free函数吧~ ⬇️


🔖2.2 free

C语言提供了free函数,那么free函数有什么用❓,我们在前边介绍了malloc函数,是用来向内存申请空间的,那么free函数就是专门用来对动态内存开辟的空间进行释放和回收。
在生活中,我们都知道有借有还,再借不难。那么在内存中也是这个道理。


free函数的原型如下:

void free (void* ptr);
  1. 如果参数ptr指向的内存空间不是动态内存开辟的,那么free函数的行为是未定义的。
  2. 如果参数ptr是NULL,则函数什么事都不做。

free和malloc所包含的头文件一样。

#include<stdlib.h>

如何与malloc搭配使用❓❓❓

代码如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//向内存开辟40个字节
	int*p = (int*)malloc(10 * sizeof(int));  
	if (p == NULL)
	{
		perror("malloc"); 
		return 1; 
	}

	//使用...... 

	//释放内存空间
	free(p); 
	p = NULL; 

	return 0; 
}

这样free函数就能够释放p所指向的动态内存开辟的内存空间,那么为什么还需要把p置为NULL呢?

是因为,free函数虽然已经释放掉了开辟的内存空间,但是指针p还是指向这一空间,为了避免野指针,所以置为了NULL。


🔖2.3 calloc

动态内存开辟的函数不仅仅是malloc函数,C语言还提供了另一种函数:calloc

calloc函数原型:

void* calloc (size_t num, size_t size);
  1. 函数有2个参数,第一个 num 为个数,第二个 size 为字节大小,那么它会开辟程序员所要求的内存空间,并且把空间的每一个字节初始化为0(malloc,值都是cd(随机值))。
  2. 当内存开辟成功,返回的是指向该内存的指针;失败时,返回NULL ,所以当我们使用时,也和malloc一样,需要检查。

calloc函数如何向内存申请空间呢?让我们接着往下看⬇️⬇️⬇️

当我需要向内存申请40个字节大小时:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//calloc向内存申请40个字节空间  
	int* p  = (int*)calloc(10, sizeof(int)); 
	//判断是否开辟成功
	if (p == NULL)
	{
		perror("calloc"); 
		return 1; 
	}
	//使用..... 
	

	//释放内存空间
	free(p); 
	p = NULL;    
	return 0;
}

结果如何? 让我们来调试看看吧~

在这里插入图片描述

我们观察到,calloc函数向内存开辟的40个字节成功,并且每一个字节初始化为0。

calloc函数和malloc函数都是向内存申请空间,既然是申请,那么也需要归还内存空间,一样的都是需要free函数释放把内存还给系统。


🔖2.4 realloc

在前边,我们介绍了malloc函数和calloc函数以及free函数,最后我们介绍realloc函数。

那么我们需要先了解,realloc函数有什么用存在的意义是什么?

其实是为了让动态内存开辟更加的灵活,有时候,我们使用malloc或者calloc申请内存空间时,可能到某一时间段发现空间太大了或者不够用小了。
那么为了对内存空间进行调整,C语言呢就提供了realloc函数,这样我们就可以对内存的大小进行灵活的调整。


realloc函数原型:

void* realloc (void* ptr, size_t size);
  1. ptr是需要调整的内存地址
  2. size是调整后的大小
  3. 返回值为调整后的内存起始位置
  4. 这个函数调整会在原内存空间的基础上,还会将原来内存中的数据移动到新的内存空间
  5. realloc函数在调整内存空间时,会分为2中情况:
    情况1:当原有空间之后有着足够大的空间,那么就会在原有空间的基础上,调整大小。
    情况2:当原有空间之后没有足够大的空间,那么会另开辟一块新的空间,并且把原有空间移到新空间,再进行调整,原有空间会被释放
    在这里插入图片描述

那么如何使用realloc函数开辟内存空间? 接着往下看吧~⬇️⬇️⬇️

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//malloc向内存开辟40个字节
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	//发现不够用,那么使用realloc函数调整内存大小
	//调整为80个字节
	int* ptr = (int*)realloc(p, 20 * sizeof(int));  
	if (ptr != NULL)
	{
		p = ptr; 
		ptr = NULL;  
	}
	else
	{
		perror("realloc"); 
		return 1; 
	}

	//使用..... 



	//释放内存空间
	free(p);
	p = NULL;

	return 0;
}

是否开辟成功?我们进行调试看看

在这里插入图片描述

我们可以看到之前malloc函数开辟的内存为40个字节,经过realloc函数调整大小后,为80个字节。


👋结束语

非常感谢您花时间阅读我的博客,希望我的分享能为您带来收获。如果您对本文有任何想法或疑问,欢迎在评论区留言交流。如果您喜欢我的博客,请继续关注,我会定期更新更多精彩内容。最后,别忘了行动起来的力量,让我们一起实践这些方法,见证自己的成长和进步!

那么到此,关于动态内存开辟就讲解完了~

再见,祝您生活愉快!

在这里插入图片描述


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

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

相关文章

MySQL-----JOIN语句之左连接、右连接

接着上文我们将基于学生&#xff0c;课程&#xff0c;考试信息三个表对内连接的总结&#xff0c;我们再来对左右连接进行一个总结&#xff0c;三个表结构以及表内数据如下图所示&#xff1a; 左连接 为了便于展示左右连接的区别&#xff0c;我们在student表里插入了一位成员…

用英语介绍端午节,柯桥零基础英语培训

端午节 Dragon Boat Festival 中国传统节日&#xff0c;农历五月初五。相传古代诗人屈原在五月初五投江自杀&#xff0c;后人把这天作为节日纪念他。有划龙舟比赛、包粽子等风俗。 A traditional Chinese festival on the fifth day of the fifth lunar month. Legend has i…

2024苹果开发者大会:Siri 接上 ChatGPT,OpenAI苹果强强联合

一直在生成式AI战争中默默无闻的苹果终于憋不住了&#xff01; 北京时间6月11日凌晨1点&#xff0c;2024苹果WWDC全球开发者大会在苹果总部 Apple Park开幕。Day 1的发布会在介绍完各个操作系统的更新后&#xff0c;一半的时间都留给了本次WWDC的重头戏——苹果AI&#xff08;…

Windows11上安装docker(WSL2后端)和使用docker安装MySQL和达梦数据库

Windows11上安装docker&#xff08;WSL2后端&#xff09;和使用docker安装MySQL和达梦数据库 1. 操作系统环境2. 首先安装wsl2.1 关于wsl2.2 安装wsl2.3 查看可用的wsl2.4 安装ubuntu-22.042.5 查看、启动ubuntu-22.04应用2.6 上面安装开了daili2.7 wsl的更多参考 3. 下载Docke…

【图书推荐】《Spark 3.0大数据分析与挖掘:基于机器学习》

本书重点 学习Spark 3.0 ML模块的机器学习算法&#xff0c;用于大数据分析与挖掘。 内容简介 Spark作为新兴的、应用范围广泛的大数据处理开源框架&#xff0c;吸引了大量的大数据分析与挖掘从业人员进行相关内容的学习与开发&#xff0c;其中ML是Spark 3.0机器学习框架使用…

rigid_trans_object_model_3d----------对3D对象模型应用刚性3D转换

Description rigid_trans_object_model_3d对3D对象模型应用刚性3D变换&#xff0c;即旋转和平移&#xff0c;并返回转换后的3D对象模型的句柄。转换由Pose中给出的姿态来描述&#xff0c;形式如下&#xff0c;其中mcsi表示输入对象模型的坐标系&#xff0c;cst表示转换后模型的…

Vue 3与ESLint、Prettier:构建规范化的前端开发环境

title: Vue 3与ESLint、Prettier&#xff1a;构建规范化的前端开发环境 date: 2024/6/11 updated: 2024/6/11 publisher: cmdragon excerpt: 这篇文章介绍了如何在Vue 3项目中配置ESLint和Prettier以统一代码风格&#xff0c;实现代码规范性与可读性的提升。通过设置规则、解…

C++入门 string(2)

目录 string类的常用接口说明 string类对象的容量操作 size & max_size & length & capacity empty & clear reserve & resize string类对象的元素访问 at & back & front string类对象的修改操作&#xff08;字符串操作&#xff09; sub…

梯度提升树GBDT系列算法

Boosting方法的基本元素与基本流程&#x1f4ab; 在Boosting集成算法当中&#xff0c;我们逐一建立多个弱评估器&#xff08;基本是决策树&#xff09;&#xff0c;并且下一个弱评估器的建立方式依赖于上一个弱评估器的评估结果&#xff0c;最终综合多个弱评估器的结果进行输出…

启明智显工业级HMI芯片Model3A功耗特性--(以M3A 7寸触摸屏为例)

** 前言&#xff1a; ** 「Model系列」芯片是启明智显针对工业、行业以及车载产品市场推出的系列HMI芯片&#xff0c;主要应用于工业自动化、智能终端HMI、车载仪表盘、两轮车彩屏仪表、串口屏、智能中控、智能家居、充电桩显示屏、储能显示屏、工业触摸屏等领域。此系列具有…

错误代码 -2147136892如何解决

错误代码 -2147136892 在 LabVIEW 中表示无法找到 CANopen 硬件。这个错误可能是由以下几个原因引起的&#xff0c;如安装不正确、端口名称错误或硬件连接问题。以下是可能的原因和详细的解决步骤&#xff1a; 可能的原因 CANopen 硬件安装不正确 硬件可能未正确安装或连接。 …

六大维度全面焕新升级!麒麟信安服务器操作系统V3.6.1引领未来计算

昨日&#xff0c;openEuler 24.03 LTS 正式发布&#xff0c;麒麟信安作为openEuler社区重要贡献者和参与者&#xff0c;充分发挥自身在国产操作系统领域的技术优势&#xff0c;在打造安全可靠、极致体验的操作系统上与社区共同努力&#xff0c;同步推出服务器操作系统V3.6.1&am…

进口不锈钢硬密封蝶阀选型-美国品牌

进口不锈钢硬密封蝶阀的选型需要综合考虑多个因素&#xff0c;以确保阀门能够满足实际工况的需求。以下是根据参考文章中的信息&#xff0c;对进口不锈钢硬密封蝶阀选型进行的详细分点表示和归纳&#xff1a; 一、流体介质 种类&#xff1a;首先明确将要处理的流体介质种类&a…

长城汽车:坚定战略往往更难

长城汽车在2024年粤港澳大湾区车展上的表现和战略方向。 以下是对通稿中信息的深入解读&#xff1a; 1. **车展亮相的重要性**&#xff1a; - 长城汽车选择在粤港澳大湾区车展这一重要平台上展示其旗舰产品&#xff0c;这不仅是对产品实力的展示&#xff0c;也是品牌影响力提升…

Marin说PCB之PCB封装库路径知多少?

小编我之前看庆余年2的时候有一段春闱考试片段&#xff0c;范闲大人四位门生只出现了三个&#xff0c;一个人一直活在其他人的嘴里&#xff0c;他就是成佳林。剧中有一段黑屏的时间其实就是致敬所有考生们&#xff0c;这个彩蛋的立意真的高啊&#xff0c;之前还没发现这个&…

关于旋转矩阵的理解,以及左乘和右乘的区别

一、对左乘一个旋转矩阵的理解 左乘旋转矩阵的旋转是相对与一个固定的坐标系的&#xff0c;这个坐标系不会因相应的向量或坐标的改变而改变&#xff0c;通常坐标系的初始位置就是固定坐标系的位置。 1&#xff09;相对于固定坐标系单次向量的旋转 这里的“单次”指的是绕RPY角…

使用 Bing 的 Chat 初体验

前言 下载好 Edge 浏览器&#xff0c;并且通过 ModHeader 插件的设置才能访问外边的功能完善的 edge &#xff0c;但是想要进行 chat 需要通过申请才行&#xff0c;网上很多教程我就不赘述了。 正文 我的申请刚刚通过&#xff0c;但是使用 Chat 的效果一般&#xff0c;感觉很…

Threejs-06、利用lil-GUI调试3D效果

1、 引入lil.gui // 引入lil.gui import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";2、创建GUI const gui new GUI();3、添加按钮 let eventObj {// 全屏事件Fullscreen:function(){// 全屏document.body.requestFullscreen();console.lo…

先导桌面式小型数控加工中心更有利于教学投入使用

桌面式 小型数控加工中心 VMC220是先导一款特色的产品&#xff0c;它体积小&#xff0c;占地面积不足1立方&#xff0c;精忠160KG左右&#xff0c;配工业级数控提供&#xff0c;机身选用优质铸铁铸造&#xff0c;采用工业级研磨滚珠丝杆&#xff0c;使用主轴伺服电机。 某高校选…

Redisson 实现分布式锁

1、相关配置 Component public class RedissonDistributedLock {Autowiredprivate RedissonClient redissonClient;public boolean tryLock(String lockKey, long expireTime, long waitTime) throws InterruptedException {RLock lock redissonClient.getLock(lockKey);retu…