一、动态内存管理库函数介绍
1.为什么存在动态内存管理
我们已经掌握的内存开辟方式有:
在栈空间上开辟内存空间
int val = 20;//在栈空间上开辟四个字节
int arr[10] = {0};//在栈空间上开辟连续的是个整形空间,40个字节
在栈空间开辟内存空间的特点:
(1)空间开辟的大小是固定的
(2)数组在申明的时候必须指定数组的长度,它所需要的内存在编译时分配
(3)对于空间的需求,不仅仅基于以上的情况,有时候我们需要的空间大小在程序运行的时候才能知道,
那数组的编译时开辟空间的方式就不能满足了。
这时候就只能试试动态存开辟了。
2.动态内存管理函数
(a)malloc
下面我们来了解库函数的介绍
1.void* —— 返回值是void* 类型的指针,这里值返回开辟好的内存空间的起始地址,
如果内存开辟失败将会返回一个NULL指针,因此malloc的返回值一定要检查
2.size_t size —— 指的是在开辟size个字节大小连续的内存空间
3.动态内存的开辟都是在堆区上开辟的,使用结束是需要返还给操作系统的
malloc()函数使用实例
int main()
{
//使用malloc在堆区开辟40个字节大小的内存空间
int* arr = NULL;
int* p = (int*)malloc(40);
if (p == NULL)
{
printf("开辟内存失败!\n");
return;//如果内粗开辟失败直接返回,程序不需要进行下去
}
arr = p;
for (int i = 0; i < 10; i++)
{
//给开辟好的内存空间赋值
arr[i] = i;
}
//打印输出
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
free(arr);
arr = NULL;
return 0;
}
(b)free
库函数介绍:
1.此函数不需要返回值
2.void* ptr —— 指传入开辟好的内存空间地址
3.上面介绍在堆区上开辟的内粗空间是需要返还操作系统的,C语言当中是有专门回收动态开辟的内存函数——free(),当然,程序结束之后也会自动释放。
free()函数使用实例:
还是以以上malloc开辟的内存空间为例子
int main()
{
//使用malloc在堆区开辟40个字节大小的内存空间
int* arr = NULL;
int* p = (int*)malloc(40);
if (p == NULL)
{
printf("开辟内存失败!\n");
return;//如果内粗开辟失败直接返回,程序不需要进行下去
}
arr = p;
for (int i = 0; i < 10; i++)
{
//给开辟好的内存空间赋值
arr[i] = i;
}
//打印输出
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
free(arr);//这时候我们已经使用完毕,释放内存返还操作系统
arr = NULL;//此时这块地址已经不属于我们使用,故要将它赋为空指针
return 0;
}
(c)calloc
库函数介绍:
C语言还提供了一个函数叫calloc,calloc函数也是用来开辟动态内存分配
(1)void* —— 返回一个void*类型的指针,指的是开辟好的内存的空间的起始地址,
如果内存开辟失败也是会返回一个NULL类型的指针,故函数的返回一定要进行判断
(2)size_t num —— 开辟内存的空间类型(比如int、char等等)的数量
(3)size_t size —— 数据类型的大小,单位为字节
(4)内存的开辟是在堆区上完成的
(5)calloc()函数与malloc()函数的区别只在于calloc会返回地址之前把申请的空间的每个字节都初始化为0
calloc()函数使用实例:
//使用calloc函数的在内存上开辟10个元素整形数组
int main()
{
int* arr = NULL;
int* p = (int*)calloc(10, 4);
if (p == NULL)
{
printf("内存开辟失败!\n");
return;//内存开辟失败直接返回,无须进行下一步
}
arr = p;
//开辟好的内存空间给它赋值
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
//打印输出
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
//释放内存,防止内存泄露
free(arr);
arr = NULL;
return 0;
}
(d)realloc
库函数介绍:
(1)有时我们发现申请的空间过小,有时候发现申请的空间过大,那为了合理的使用内存,我们一定会对内存的大小做灵活的调整。那realloc()函数就可以做到对动态开辟的内存大小做出调整。
(2)void* —— 函数返回一个在堆区调整好的内存起始地址
(3)void* ptr —— 用malloc()函数或者calloc()函数开辟好的内存的起始地址
(4)size_t size —— 要调整的内存新大小,单位为字节
(5)这个函数调整原内存空间大小的基础上,还会将原内存的数据移动到新的空间
realloc()函数使用实例:
int main()
{
int* arr = NULL;
int* p = (int*)malloc(10*sizeof(int));
if (p == NULL)
{
printf("开辟内存空间失败!");
return;
}
arr = p;
//给开辟的内存空间赋值
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
//打印输出
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//当我们的内存不够的时候,用realloc()函数进行调整
int* ptr = (int*)realloc(p, 20*sizeof(int));
if (ptr == NULL)
{
printf("扩容失败!");
return;
}
arr = ptr;
//对扩容后的内存继续使用
for (int i = 10; i < 20; i++)
{
arr[i] = i;
}
for (int i = 0; i < 20; i++)
{
printf("%d ", arr[i]);
}
free(arr);
arr = NULL;
return 0;
}
每个人的成长和进步都离不开点点滴滴的积累,如果小编的内容对您有所帮助,希望友友们三连加关注哦,你的支持是小编创作的最大动力。