文章目录
- 一、什么是动态内存管理
- 二、动态内存函数的介绍
- 1.malloc函数的介绍
- 2.calloc函数的介绍
- 3.realloc函数的介绍
- 三、free函数的介绍
一.什么是动态内存管理
我们知道数据都是在内存中进行储存的,但是如果我们需要调用内存,我们可以通过定义一个变量向内存中申请空间,例如
int a = 0;
int arr[10] = { 0 };
诸如此类的都是通过定义的形式对空间进行开辟。
但是这种调用内存的方式会存在一定的缺陷
1.他们所开辟的大小都是固定的
2.数组在定义申明的时候,必须要指定数组的长度大小,有的时候我们需要的空间大小在程序运行之后才能知道。
所以,动态内存管理的作用就很明确了,是通过一个动态内存函数来对空间进行开辟,从而达到我们想要的一个效果。
二. 动态内存函数的介绍
动态内存函数在使用之前需要引用头文件 #include <stdlib>
1.malloc函数的介绍
malloc函数的一般形式是 void* malloc (size_t size);
void* 是malloc的类型,一般情况下需要对malloc进行强制转换操作,例如(int *)malloc等。
它的作用是向内存中开辟一块内存块,并且返回给一个指向内存空间的指针。
需要注意的是,如果开辟成功的话,则会返回一个指向内存空间的指针。
若是开辟失败的话则会返回一个NULL指针,所以需要对malloc的返回值进行检查
如果size为0,malloc的标准行为是未定义的,这个取决于编译器.
我们通常可以这样来使用malloc.
int main() { int* p = (int*)malloc(40);//开辟一块大小为40个字节的空间 if(p == NULL)//对返回值进行检查. { perror("malloc"); return 1; } return 0; }
这个程序可以理解为int p[10] = { 0 };但是malloc在开辟完空间之后,是不会对内存进行初始化的,会保留一个不确定的值。
2.calloc函数的介绍
calloc的用法和malloc大体相似,但也有些不同。
它的基本形式是void* calloc (size_t num, size_t size);在这里,num是需要分配的元素的大小。size是元素本身的字节大小。
其次,calloc的返回值同样需要检查。
若开辟成功则会返回一个指向空间的指针。
若是开辟失败,则会返回一个NULL指针。
若为0,则返回值就取决于特定的库实现(它可能是也不是空指针),但是返回的指针不应该被取消引用。
通常对calloc的使用格式如下:
int main() { int* p = (int*)calloc(10, sizeof(int));//开辟一块大小为40字节的空间 if(p == NULL)//对返回值进行检查 { perrpr("calloc"); return 1; } return 0; }
同样和malloc一样是对内存空间进行开辟,但是calloc在开辟内存空间的时候会对内存空间进行初始化操作。
3.realloc函数的介绍
realloc函数是对内存大小进行重新分配,通常会用于扩容或者是缩进内存空间大小。
realloc的基本形式是void* realloc (void* ptr, size_t size);
这里的ptr是指向需要进行操作的空间的一个指针,类型是根据指针的类型来变化的,size是变化后的空间大小,这里尤其需要注意,并不是需要扩容/缩进的大小,而是扩容/缩进之后的整个空间的大小。
realloc在调整原空间大小的基础上,还会将原来的内存中的数据移动到新的空间。
并且,realloc在调整内存空间上存在两种情况:
1.原有空间之后拥有足够大的空间
若原有空间后拥有足够大的空间,则realloc函数会直接在该空间的后面进行开辟。
2.原有空间之后的空间不足
若原有空间后拥有的空间不足以进行调整,则realloc函数会通过重新开辟一块空间并调整为新的大小,然后通过将原空间内的数据进行拷贝到新的空间内,其次会对旧的空间进行释放,最后会返回一个新的空间地址。
我们通过一个案例来说明一下:
int main()
{
int* p = (int*)malloc(40);
if(p == NULL)
{
perror("malloc");
return 1;
}
p = realloc(p, 80);
return 0;
}
调整前的空间的地址
调整后的空间的地址
通过以上的对比我们可以了解到空间不足的情况下确实会重新开辟一块空间来进行对内存空间大小的调整。
三.free函数的介绍
在使用free函数前,同样需要引用头文件#include <stdlib.h>
我们通过定义变量对内存进行开辟的方式称为静态开辟内存空间,而我们通过静态开辟的内存会由系统自动进行释放。
但是动态开辟的内存,malloc和calloc开辟的内存空间并不会由系统主动释放,若我们不通过主动释放的话,这块空间很有可能会导致内存泄漏等问题,所以在结束对内存的动态开放之后,我们需要主动对动态开辟的内存空间进行释放。
在这里就需要引进free函数。free函数就是用于释放我们动态开辟的空间。
它的用法也非常的简单,它的参数就是指向我们动态开辟的空间的那个指针。
例:
int main
{
int* p = (int*)malloc(40);
if(p == NULL)
{
perror("malloc");
return 1;
}
free(p);
p = NULL;//需要将指针设置为空指针
return 0;
}
注意在对内存空间进行free后,需要将指针的大小置为NULL,防止野指针的产生。
同样,如果指针指向的空间并不是动态开辟的,则free函数的行为是未定义的。free函数只针对动态开辟的空间,对于静态开辟的内存空间,free函数的行为是未定义的。
如果ptr的值为NULL的话,则free函数什么也不会做。
以上就是对动态开辟内存空间的介绍,如果该文对你有帮助的话不要忘记点赞+关注三连一下,欢迎各位佬的关注与支持,顺着网线回去三连!