动态内存管理

又是一个周一,每一个明天都是未知的,我们只有把握好今天,那么在未来的某一个明天才会有惊喜等着你,它就在那里等着你的,你可不能半途而废呀!

本期的内容,我们一起来学一学C语言中的动态内存管理,学好这一章,那对于我们后面学习数据结构是有很大帮助的!

🐷1. 为什么要有动态内存分配:

在已有的知识中,我们已经知道内存的开辟方式,例如:

int a = 0;//在栈空间上开辟4个字节
char c  = 0;//在栈空间上开辟1个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
那么我们可以发现,上述的开辟空间的方式有两个特点:
😊• 空间开辟大小是固定的。
😊• 数组在申明的时候,必须指定数组的⻓度,数组空间⼀旦确定了大小不能调整
但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知
道,那数组的编译时开辟空间的方式就不能满足了。
那么C语言为了解决这类问题,引⼊了动态内存开辟,让程序员⾃⼰可以申请和释放空间,就比较灵活了。

🐇2. malloc和free:

🐇malloc:

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

那么我们可以看见,如果没有给申请的空间赋初值的话,那么空间内就是一些随机值!那么它真的会有申请失败的时候吗?答案是有的:

使用该空间:

 那么我们申请了空间,是不是用完了该还回去呢,这样我们下次才好去借呀,哈哈!

🐇free:

free函数用来释放动态开辟的内存。
😊• 如果参数 ptr 指向的空间 不是动态开辟 的,那free函数的行为是未定义的
😊• 如果参数 ptr 是NULL指针,则函数什么事都不做。
注:malloc和free都声明在 stdlib.h头文件中。

那么将 p赋为空指针是否有必要呢?如果不赋为空指针的话,那么我们的p还是会指向刚刚申请的空间,但那块空间已经释放还给操作系统了,所以为了避免p以后成为野指针,这里将它赋为空指针。


🐻3. callocrealloc:

🐻calloc:

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

 

🐻 realloc:

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

😊• ptr 是要调整的内存地址
😊• size 调整之后新大小
😊• 返回值为调整之后的内存起始位置。
😊• 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

😊• realloc在调整内存空间的是存在两种情况:

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

要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化。

情况2:原有空间之后没有足够大的空间
原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适大小的连续空间来使⽤。这样函数返回的是⼀个新的内存地址。

当我们给realloc函数传NULL时,这时realloc相当于我们的malloc。


🐱4. 常见的动态内存的错误:

🐱4.1 对NULL指针的解引用操作:

🐱4.2 对动态开辟空间的越界访问 :

🐱4.3 对非动态开辟内存使用free释放 :

🐱4.4 使用free释放⼀块动态开辟内存的一部分 :

🐱4.5动态开辟内存忘记释放(内存泄漏) :


🐕5. 柔性数组:

柔性数组(Flexible Array)是一种特殊的数据结构,它允许在结构体的末尾定义一个具有可变长度的数组。柔性数组的大小在运行时确定,这使得它成为处理变长数据的一种灵活的选择。

柔性数组的声明方式是将一个未知大小的数组放置在结构体的末尾,但是这个数组的大小可以在结构体实例化之前或之后进行动态分配。

🐕6.1柔性数组的特点:

😊• 结构中的柔性数组成员前⾯必须⾄少⼀个其他成员。

😊• sizeof 返回的这种结构大小不包括柔性数组的内存。

😊• 包含柔性数组成员的结构⽤malloc ()函数进⾏内存的动态分配,并且分配的内存应该⼤于结构的大小,以适应柔性数组的预期大小。

4个字节?说明sizeof在计算时,没有计算数组arr的大小,因为它此时就是为柔性数组,大小是未知的。

🐕6.2 柔性数组的使用:

对于上述的代码,我们也可以用另外种方法来完成。我们先为结构体申请一块空间,然后再为数组申请一块空间 。

上述 代码1 和 代码2 可以完成同样的功能,但是 ⽅法1 的实现有两个好处: 

第⼀个好处是:方便内存释放
第⼆个好处是:这样有利于访问速度

而且我们的柔性数组还可以应用其他的地方:柔性数组在处理变长数据时非常有用,比如处理网络数据包、文件格式等。它提供了更灵活的内存管理方式,使得我们能够高效地操作变长数据。

时光总是短暂的,相逢的时间总是那么地短暂,希望往后的每一次的相遇都会是更好的你,本期就到这里就结束咯,希望会对你有所帮助!时光不语,却回答了所有问题!

  • 51
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

并不会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值