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

精通C语言(4.四种动态内存有关函数)

在这里插入图片描述
🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言
🔥专栏:《C语言入门知识点》、《C语言底层》、《精通C语言》、《C语言编程实战》
💪格言:做好你自己,你才能吸引更多人,并与他们共赢,这才是你最好的成长方式。


前言:

我们提法C语言或者说各种编程语言,其实就是与他们对内存的处理打交道,今天依旧是围绕内存来做一些文章:动态内存管理。包括接下来的几篇也都是关于动态内存管理的文章,今天我们先来了解一下四个有关动态内存管理的函数吧,记好笔记出发喽~


文章目录

  • 前言:
  • 正文:
    • 1.为什么要有动态内存管理
    • 2. malloc函数和free函数
      • 2.1 malloc函数
      • 2.2 free函数
    • 3. calloc函数和realloc函数
      • 3.1 calloc函数
      • 3.2 realloc函数


正文:

1.为什么要有动态内存管理

我个人认为,你学一个东西,你一定要带有目的性的学,就像是你高中时,学习很大程度上本来就是为了高考服务的,而到了大学乃至其他阶段,你学习更要有一个目标,漫无目的的学是行不通的,你连学一个知识的目的是什么都不知道,你怎么能学好它

那我们就开始,到底什么是动态内存管理,以及为什么需要动态内存管理

我们平时开辟内存空间是怎么开的呢?我们知道两种方式:

int i = 0;
int arri[30] = { 0 };

这两种方式一种是直接以整型为单位开辟四个字节的空间,另一种是以数组为单位来开辟想要的空间大小
但是这两种方式,他们对空间的开辟都是固定的,对于数组,就有三种情况:
① 我们现在需要存大于30个整数,那么上面的空间显然就不够通用了
②刚好够用
③需要存小于30个整数,上面的空间就多出来了,会被浪费掉

这种时候第二种当然是最好的,但是我们很难保证每次都是第二种情况,这个时候就需要动态内存管理了

2. malloc函数和free函数

先直观的来说malloc函数是用来开辟空间的,free函数是用来释放空间的

malloc中的mmemory存储 ”的意思,allocallocate开辟 ”的意思
free是“自由 ”的意思

下面我们看一下他们在C语言标准库中的描述

  1. malloc
    在这里插入图片描述
  2. free
    在这里插入图片描述

可以看到他们都是在头文件<stdlib.h>中的函数
下面是他们的作用,意为"开辟内存空间"和“释放内存空间

那我们来看看具体怎么用吧:

2.1 malloc函数

标准形式:

void* malloc(size_t size);

返回结果

  1. 如果成功则返回指向开辟的初始地址的指针
  2. 如果失败则返回NULL这个空指针
  3. 如果size为0,会根据编译器不同产生不同的结果

演示:

//x64环境下
//void* malloc(size_t size)
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
int* ptr = (int*)malloc(INT_MAX);
if (p != NULL)
{printf("yes\n");
}
if (ptr != NULL)
{printf("yes\n");
}
printf("p申请大小: %zu\n", 10 * sizeof(int));
printf("ptr申请大小: %zu\n", (size_t)INT_MAX * sizeof(int));  // 观察是否溢出
return 0;
}

运行结果:

yes
yes
p申请大小: 40
ptr申请大小: 8589934588
//x86环境下
//void* malloc(size_t size)
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
int* ptr = (int*)malloc(INT_MAX);
if (p != NULL)
{printf("yes\n");
}
if (ptr != NULL)
{printf("yes\n");
}
return 0;
}

运行结果:

yes

为什么两种情况下会不一样呢?

  1. 在 x64 环境下,系统理论上可以访问非常大的虚拟地址空间(最大可达 2^64 字节),相比 x86 环境,它能利用的内存资源更充足。
  2. 在 x86 环境(32 位系统)下,系统能访问的虚拟地址空间最大为 4GB ,这就导致了malloc函数必然申请不到足够的连续的内存空间。

2.2 free函数

标准形式:

void free(void* ptr)

返回结果:

  1. 如果ptr不是动态内存开辟的指针,那free的行为是未被定义的
  2. 如果ptr是一个NULL,那free将没有行为,什么都不做

演示:

//void free(void* ptr)
int main()
{int* ptr = (int*)malloc(10 * sizeof(int));//这里的10可以用过变量代替if (ptr != NULL){int i = 0;for (i = 0; i < 10; i++){*(ptr + i) = 0;}}free(ptr);ptr = NULL;return 0;
}

这就是一个完整的free函数搭配malloc函数的代码
free是释放内存空间的,但是后来一定得使空间置空,不然还是可以找到,导致麻烦

主要有三个麻烦之处

  1. 误用已释放的内存(内存访问错误)
free(ptr);
// 未执行 ptr = NULL;
*ptr = 10;  // 错误:向已释放的内存写入数据,属于访问非法内存
  1. 重复释放内存(二次释放错误)
free(ptr);
// 未执行 ptr = NULL;
free(ptr);  // 错误:重复释放同一内存块
  1. 条件判断失效(逻辑错误)
free(ptr);
// 未执行 ptr = NULL;
if (ptr != NULL) {  // 错误:野指针非空,判断为“有效”*ptr = 20;      // 实际访问已释放内存
}

3. calloc函数和realloc函数

同malloc函数一样,他们两个函数都是用来开辟内存空间的

calloc函数中cclear清零 ”的意思,realloc函数是reallocate重新分配 ”的意思

依旧是看从语言标准库中的描述:

  1. calloc
    在这里插入图片描述
  2. realloc
    在这里插入图片描述

依旧是头文件<stdio.h>中的函数
callocmalloc效果唯一不同的一点就是他会把开辟的内存空间全部初始化成0
realloc则是对已有的空间进行重开辟

3.1 calloc函数

这里就直接演示一下:

int main()
{int* ptr = (int*)calloc(10, sizeof(int));int i = 0;for (i = 0;i < 10; i++){printf("%d %d\n", *(ptr + i),i+1);}free(ptr);ptr = NULL;return 0;
}

运行结果:

0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
0 10

可以看到开辟出的内存储存的值全部都是0

3.2 realloc函数

realloc函数的出现让动态内存管理更加灵活。
有时会我们发现过去申请的空间太⼩了,有时候我们⼜会觉得申请的空间过⼤了,那为了合理的使⽤内存,我们⼀定会对内存的⼤⼩做灵活的调整。
realloc 函数就可以做到对动态开辟内存⼤⼩的调整。

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

ptr是指向要调整的地址的指针
size是调整后的空间大小
返回值为指向调整后的地址的指针

但是realloc实际上会有两种情况:

在这里插入图片描述

这就导致会有不一样的结果:

  1. 当是情况1的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化。
  2. 当是情况2的时候,原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适⼤⼩的连续空间来使⽤。这样函数返回的是⼀个新的内存地址

使用案例:

//代码一,ptr是原开辟地址
ptr = (int*)realloc(ptr, 1000);
//代码二
int* p = NULL;
p = realloc(ptr, 1000);
if (p != NULL)
{ptr = p;
}

这两种代码是对于原地址的两种处理结果
需要注意的是,第一种一旦发生空间不够位置改变,原来的数据就很难再找回来了
所以正确的应该是第二种

  • 以上就是四种动态内存管理的基础知识了,希望对大家有所帮助

  • 本节完…
http://www.dtcms.com/a/465537.html

相关文章:

  • 【实用工具】使用Python语言制作RSS阅读器
  • 动态规划 - 二维费用的背包问题、似包非包、卡特兰数
  • JAVA·方法的使用
  • 做rap的网站国内做网站网站风险大吗
  • 【代码随想录算法训练营——Day33】动态规划——62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树
  • 基于单片机的元胞自动机仿真系统设计
  • 星座运势网站技术解析:从零打造现代化Web应用
  • Asp.net core 跨域配置
  • Java学习之旅第二季-18:转型
  • 建筑物孪生模型:重构空间数字化格局,赋能智慧城市
  • Claude code、codex、gemini cli开启全自动(yolo)模式,无需审批
  • wordpress账号和站内网建网站需要注册公司吗
  • 24软件测试计划主要工作和确定测试资源
  • 【每天一个知识点】[特殊字符] 大数据的定义及单位
  • ICT 数字测试原理 17 - -VCL中的预处理
  • 领码方案|微服务与SOA的世纪对话(7):运营降本增效——智能架构时代的成本与服务管理
  • YOLO v1:目标检测领域的单阶段革命之作
  • 河北建设厅八大员报名网站中国网库网站介绍
  • 基于RuoYi框架+Mysql的汽车进销存后台管理系统
  • 网站底部导航制作制作视频特效
  • 南宁网站建设索王道下拉建设网站的法律声明
  • Java中Mock的写法
  • 在JavaScript / HTML中,调整div的边框
  • 关于margin:auto的注意点
  • 23种设计模式——责任链模式(Chain of Responsibility Pattern)
  • istio 为什么在主机上抓不到15001和15006的流量
  • 怎么建设电子邮箱网站wordpress国外空间
  • 网站内容页怎么设计模板网络建设与维护公司
  • 网页版的点名/抽奖程序
  • 学做课件的网站商丘seo快速排名