目录
前言
malloc函数
free函数
calloc函数
realloc函数
前言
在这一章节将讲解动态内存分配,它可以在程序的堆区创建一块内存,在这块内存中存什么值就是由自己决定的了
开辟的空间有两个特点:
1. 空间开辟的大小是固定的
2. 数组在声明时必须指定长度,数组的大小一旦确定就不能调整
在使用这些函数之前我们需要包含他们头文件
#include<stdlib.h>
malloc函数
该函数的作用是开辟一块固定大小连续的空间,并返回指向这块空间的指针
所以它的返回值为void*
里面的参数size是一个以字节为单位的数字,函数会开辟所给的大小
如果malloc开辟空间成功,则按上面所说返回一个指向这块空间的指针
如果malloc开辟空间失败,则会返回NULL指针
因此使用它时一定要进行检查返回值
如果传的size为0,则具体怎么处理看编译器
具体使用malloc函数的代码如下:
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = malloc(sizeof(int) * 4);if (p == NULL){perror("malloc fail");return 1;}for (int i = 0; i < 4; i++){p[i] = i + 1;}for (int i = 0; i < 4; i++){printf("%d ", p[i]);}return 0;
}
首先我们定义了一个int* 类型的指针接收malloc的返回值
并且使用了if 语句判断malloc开辟空间是否成功,如果成功则不会进入if 语句进入下面的语句
然后下面的两个for循环就是正常的给空间赋值和打印,最终结果如下:
但是这样做其实还差了点意思,这个程序其实并不完美,存在内存泄漏的问题
假设我们需要一直跑某一个代码,那么我们如果这样一直使用内存不进行释放的话,迟早有一次内存会被吃满,这种现象叫做内存泄漏
所以为了解决这个问题,我们需要使用另一个函数
free函数
free是专门用来做动态内存的释放和回收的
该函数没有返回值,参数为一个void* 的指针(想了解void*可以看看我前面的博客)
C语言:指针的基础详解-CSDN博客
注:
1. 如果ptr指向的空间不是动态开辟的,则free函数的行为是未定义的(具体处理方式看编译器)
2. 如果ptr是NULL指针,则函数什么事情都不做
所以与上面动态开辟内存的malloc函数结合起来使用,我们在上面写的代码只需要在最后加上一个free函数释放掉这块空间即可
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = malloc(sizeof(int) * 4);if (p == NULL){perror("malloc fail");return 1;}for (int i = 0; i < 4; i++){p[i] = i + 1;}for (int i = 0; i < 4; i++){printf("%d ", p[i]);}free(p);p = NULL;return 0;
}
最后free的参数为p表示释放掉p指向的这块动态开辟的空间
并且我们可以在最后将p置为空指针,以防它变成野指针
calloc函数
calloc跟malloc基本差不多
第一个参数num是需要开辟的空间数量
第二个参数size是每个空间的大小
返回值与malloc一样
calloc与malloc的本质区别就是calloc会将开辟的那块空间的每个字节初始化为0
总结:calloc会初始化,malloc不会初始化
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = calloc(4, sizeof(int));if (p == NULL){perror("malloc fail");return 1;}for (int i = 0; i < 4; i++){printf("%d ", p[i]);}free(p);p = NULL;return 0;
}
前面的代码我们将malloc换成了calloc,并且将初始化的环节删除了,最终输出结果如下:
可以看到我们并没有给它初始化但是打印出来的结果是0
所以这个函数已经将这块空间给初始化为0了
realloc函数
realloc让动态内存管理更加灵活了
有时候我们会发现申请的空间太小了,有时候又觉得申请的空间太大了浪费,为了合理的使用内存
我们可以使用realloc函数进行调整
第一个参数ptr是要调整的内存地址
第二个参数是调整之后的新大小
函数返回值为调整之后的内存起始位置
realloc调整空间有两种情况
情况1:原有空间之后有足够大的空间
情况2:原有空间之后没有足够大的空间
如果是情况1则会直接在原来的空间后面直接追加空间,最后返回原来的内存地址
如果是情况2则会在堆空间上另外找一个合适并且有足够大小的空间进行开辟,最后返回新的内存地址
具体代码如下:
#include <stdio.h>
#include <stdlib.h>int main()
{int* p = malloc(sizeof(int) * 4);if (p == NULL){perror("malloc fail");return 1;}int* ptr = realloc(p, sizeof(int) * 6);for (int i = 0; i < 6; i++){ptr[i] = i + 1;}for (int i = 0; i < 6; i++){printf("%d ", ptr[i]);}free(p);p = NULL;return 0;
}
第一个malloc开辟了四个int类型的空间,若此时我们发现不够,则以下用了realloc调整空间
下面使用了ptr来接收realloc将p指向的空间变成6个int类型的空间的起始地址
最后我们给ptr赋值并且打印,结果如下:
完