C语言:动态内存管理(malloc,calloc,realloc,free)

目录

前言

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赋值并且打印,结果如下:


  • 41
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ragef

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值