文章目录
#1 前言 为什么需要动态内存管理
静态开辟内存有两个特点:
1.空间开辟大小是确定的。
2.若是数组,那么需要指定明确数组的长度,不能使用变量。
但实际使用中可能会出现需要开辟未知大小空间,或者是需要调节已开辟空间的情况,静态开辟无法满足需求。
此时就需要动态内存管理了。
#2 动态内存函数
动态内存的优点是使用灵活,缺点是开辟出的空间需要另外释放。
首先,想要使用C语言自带的动态内存函数,需要包含头文件。
#include <stdlib.h>
#2.1 malloc
malloc的基本格式
void* malloc (size_t size);
参数为想要申请的空间大小,单位为字节。
这个函数向内存申请一块连续的空间,并返回这个空间的起始地址。
需要注意的是,动态开辟可能失败,此时返回的就是空指针。
开辟成功时,返回值的类型是void*,需要申请者自己根据情况强制转换为需要的类型。
#2.2 calloc
calloc的基本格式
void* calloc (size_t num, size_t size);
第一个参数为为元素的个数,第二个参数为每个元素的大小。
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
因为该函数会帮你初始化,但函数并不知道你所需求的数据类型,所以需要使用者自己指定每个元素的字节大小。
该函数日常使用较少,用的更多的还是malloc和下文的realloc。
#2.3 realloc
在需要调节已有动态开辟空间大小时,就要用到realloc。
在原空间之后连续追加空间,达到修改空间大小的目的。
realloc的基本格式
void* realloc (void* ptr, size_t size);
第一个参数ptr为待修改大小的动态开普空间,第二个参数为修改后的空间大小,单位为字节。
同样返回原空间或者新空间的起始地址。
如果第一个参数为空指针,那么该函数就可以等价于malloc函数。
调用该函数后有两种情况:
情况1:原空间之后空间足够,在后面接着连续开辟。此时就会返回原空间地址。
情况2:原空间之后空间不够,此时有如下步骤:
1.开辟新的空间。
2.将旧空间中的数据拷贝至新空间。
3.释放旧的空间。
4.返回新空间的起始地址。
这些步骤是函数自己完成的,不需要使用者另外操作。
#2.4 free
动态开辟出的空间,无一例外都需要free函数来释放,否则就会造成数据泄露。
free的基本格式
void free (void* ptr)
free的使用很简单,只需要将动态开辟出的指针作为参数传递,就可以释放该空间。
如果传参为空指针,那么free函数将什么也不做。
空间被释放后,原指针变量就变成了野指针,从安全的角度来说,应该将其置空。
#2.4.1 只能对动态开辟的内存使用free
free函数是与上述三种动态开辟函数绑定的。
对于不是动态开辟出的内存空间,不能使用,也无需使用free函数来释放。
#2.4.2 不能使用free释放部分动态开辟空间
每次动态开辟出的空间都是完整连续的,释放时也必须完整的释放。
释放部分动态空间的做法是不可取的。
#2.4.3 未释放(内存泄漏)
如果动态开辟出的空间没有释放,那么这块空间在程序结束之前就会一直被占用,这部分的内存就无法使用了。甚至如果该空间的指针丢失了,就造成了内存泄漏。
所有动态开辟的空间都需要释放。使用的时候需要加强注意。