动态内存管理

2023-12-14 20:17:58

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

本期的内容,我们一起来学一学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 的实现有两个好处:?

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

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

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

文章来源:https://blog.csdn.net/2302_77675796/article/details/134923110
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。