当前位置: 首页 > news >正文

C语言---动态内存管理

为什么要有动态内存分配

        我们在学习动态内存管理之前,一直都是通过开辟变量,或者是开辟数组的方式来在内存的栈区开辟空间的,但是这样的开辟方式有局限性,因为一旦开辟之后,它们的大小就无法改变,就缺少了很多的灵活性,但是动态内存管理就可以帮助我们解决这个问题,它是在堆区开辟空间的,并且它所开辟的空间是可大可小的。

动态内存开辟四大函数

        其实想要动态开辟内存空间非常的简单,我们只需要学会内存开辟四大函数就可以了。

        malloc和free

        malloc函数就是用来在内存的堆区开辟空间的,它的函数定义如下。

   void* malloc (size_t size);

   函数的形参表示所要开辟空间的字节大小,你想要开辟几个字节的空间,就给形参什么值,malloc函数是在堆区开辟的一块连续的空间,一旦开辟了空间,我们想要找到这块空间,就势必要只要它的起始地址值,而malloc函数的返回值就是这个作用,它返回的是开辟空间的起始地址,那为什么是void*类型的指针呢?原因就是我在开辟的时候,我也不知道要往这块空间里边存放什么类型的数据,或者说什么类型的数据都可以存放在我这块空间里边,所以一开始就给它返回的是void*类型的指针。还有一个值得注意的点就是malloc开辟空间如果失败的话,就会返回NULL值,所以我们需要对返回值进行判断。

        malloc函数的使用举例

#include<stdio.h>
#include<stdlib.h>//四大内存开辟函数都需要包含这个头文件int main()
{//假设现在我想要开辟40个字节的空间,并且像里边存放整型数据int* pi = (int*)malloc(40);//判断是否开辟成功//为NULL就代表开辟空间失败,perror打印开辟失败的原因//返回非0的值,C语言里边返回非0的值表示异常结束if (pi == NULL){perror("malloc");return 1;}//开辟成功,可以向这块空间里边存值for (int i = 0; i < 10; i++){*(pi + i) = i + 1;//存入1~10的值}//打印for (int i = 0; i < 10; i++){printf("%d ", *(pi + i));}return 0;
}

        由上边的代码跟运行结果来看,好像似乎并没有什么问题,但malloc毕竟是动态开辟的空间,开辟了空间难道就不用回收的吗?答案是要回收的,上边的代码好像并没有回收,那怎么也可以运行呢,原因是当程序结束的时候,操作系统会自动帮你回收,不过如果日后的代码过长,或者是程序是一个7*24小时不停歇的运转的话,如果我们不主动回收,就会出现内存泄露的问题,所以如果这块动态开辟的内存你不再想要使用的时候,就请主动回收掉,free函数就是用来主动回收的。

        free:

   它的函数定义如下

   void free (void* ptr);

   它的形参的指针就指向的是动态开辟的起始地址的位置,如果给它传NULL,那么这个函数将什么都不会做。

   接下来我们对刚才的代码做一个完善   

        由图可见,释放代码其实就两行,但是至关重要。

        大家可能会有疑惑,释放完了空间之后,为什么还要将pi赋值为NULL指针,原因是因为刚才的pi指针接收了malloc动态开辟的空间,但是当free之后,刚才申请的那块空间已经被释放了,里边的数据也已经不是刚才存进去的数据了,而此时pi指针里边仍存放着那块空间的地址,这就形成了野指针,所以给它赋值为NULL。

        calloc和realloc

        calloc函数也是用来动态内存开辟空间的函数,它的函数定义如下

   void* calloc (size_t num,size_t size);

   函数的形参的意思就是为num个大小为size的元素开辟空间,并且calloc函数会把开辟的空间的每个字节都初始化为0。

        calloc函数的使用举例

#include<stdio.h>
#include<stdlib.h>
int main()
{//给10个大小为int类型的数据开辟空间//用malloc函数就相当于//malloc(10 * sizeof(int));int* pi = (int*)calloc(10, sizeof(int));if (pi == NULL){perror("calloc");return 1;}//开辟成功,使用//calloc会自动的给申请的空间初始化为0for (int i = 0; i < 10; i++){printf("%d ", *(pi + i));}//释放free(pi);pi = NULL;return 0;
}

        realloc函数是用来对我们动态申请的内存进行调整的。它的函数定义如下。

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

   ptr是要调整空间内存的起始地址。size为调整之后的新大小。返回值为调整后的内存的起始位置。

        对于realloc函数的重新调整空间大小,总共有三种情况。

        情况1:原有空间之后有足够的空间。

        情况2:原有的空间之后没有足够的空间。

        情况3:重新调整空间失败,返回NULL指针。

        realloc函数的使用举例

#include<stdio.h>
#include<stdlib.h>
int main()
{//申请空间int* pi = (int*)malloc(40);if (pi == NULL){perror("malloc");return 1;}//使用空间for (int i = 0; i < 10; i++){*(pi + i) = i++;}for (int i = 0; i < 10; i++){printf("%d ", *(pi + i));}//内存不够,重新调整//注意,这个返回值不能用刚才的pi来接收,因为可能开辟空间失败返回NULL,这样就导致原来开辟的空间也找不到了。int* ptr = (int*)realloc(pi, 80);if (ptr == NULL){perror("realloc");return 1;}else//开辟成功{pi = ptr;ptr = NULL;}//继续使用........//释放空间free(pi);pi = NULL;return 0;
}
http://www.lryc.cn/news/591798.html

相关文章:

  • mingw 编译 assimp v6.0.2 解决编译报错
  • Vue3 + WebSocket
  • 云徙科技----一面(全栈开发)
  • 使用 docker 安装 openldap
  • 腾讯会议本地录屏转存失败解决办法
  • 【数据结构】链表(linked list)
  • BI Agent vs. 传统BI工具:衡石科技视角下的效率与智能跃迁
  • 算法讲解-移动零
  • properties中文乱码
  • 深入解析Linux进程创建与fork机制
  • 学习日志12 python
  • 强化第三讲—一元函数微分学的概念
  • LIN协议核心详解
  • 【Dv3Admin】传递数据实现查询功能
  • Mac OS上docker desktop 替代方案
  • 【JavaEE进阶】使用云服务器搭建Linux环境
  • 数据结构排序算法总结(C语言实现)
  • Leetcode刷题营第二十九,三十题:二叉树的中序以及后序遍历
  • Docker 镜像原理
  • 在windows平台上基于OpenHarmony sdk编译三方库并暴露给ArkTS使用(详细)
  • 深入理解Java中的Map.Entry接口
  • AI问答-供应链管理:各种交通运输方式货运成本分析
  • C/C++---rdbuf()函数
  • 建筑兔零基础人工智能自学记录111|初识comfyui-20
  • 系统设计时平衡超时时间与多因素认证(MFA)带来的用户体验下降
  • VMware Workstation Pro 17下载安装
  • 安装wsl-Ubuntu到D盘
  • 微信远程控制系统2.0
  • 如何下载视频 (pc端任何视频均可下载)
  • 通义万相-文生视频实践