当前位置: 首页 > 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.dtcms.com/a/284545.html

相关文章:

  • 李宏毅《生成式人工智能导论》 | 第15讲-第18讲:生成的策略-影像有关的生成式AI
  • Google(谷歌)搜索引擎蜘蛛IP地址段
  • ubuntu--curl
  • 《Java Web 核心:Servlet、会话与过滤器笔记》
  • AndroidStudio环境搭建
  • vue svg实现一个环形进度条组件
  • 石子入水波纹效果:顶点扰动着色器实现
  • 【44】MFC入门到精通——MFC 通过Button按钮添加控件变量实现:按下 按钮变色 (比如开关 打开关闭状态) MFC更改button控颜色
  • Git简介与特点:从Linux到分布式版本控制的革命
  • 找不到或无法加载主类 org.gradle.wrapper.GradleWrapperMain
  • Linux Swap区深度解析:为何禁用?何时需要?
  • 【Java EE初阶 --- 网络原理】网络编程
  • Vue3 + WebSocket
  • 基于现代R语言【Tidyverse、Tidymodel】的机器学习方法
  • 3.2 函数参数与返回值
  • .vscode 扩展配置
  • 浅析网络安全面临的主要威胁类型及对应防护措施
  • 【C++指南】C++ list容器完全解读(四):反向迭代器的巧妙实现
  • 如何做好DNA-SIP?
  • 【41】MFC入门到精通——MFC中 GetLBText()、GetWindowText()、SetWindowText区别
  • 扭蛋机小程序开发:开启线上娱乐新风尚
  • 分布式光伏发电系统中的“四可”指的是什么?
  • 教资科三【信息技术】— 学科知识: 第一章(信息技术基础)
  • 基于springboot+vue+mysql技术的实验室管理系统(源码+论文)
  • 044_设计模式入门(创建型 / 结构型 / 行为型)
  • 【解决方案】鸿蒙 / 矿鸿系统 Shell 无故退出问题(息屏导致)详解
  • Spatial Frequency Modulation for Semantic Segmentation。针对图像下采样造成信息丢失问题的解决思路
  • 深入理解 Spring Boot Starter 的生成机制
  • tcp/udp调试工具
  • Linux内核网络栈深度剖析:inet_connection_sock.c的服务器端套接字管理