空间用多少我说了算! C语言动态内存!

为什么存在内存分配

我们之前学的内存分配,都是直接开辟内存。但是这样有一个问题:我们开辟的内存是大了还是小了,会不会浪费,会不会不够用。有的程序只有在运行的时候才知道要用多少空间。所以为了解决这样的问题,我们就有了内存的动态开辟。

动态内存都是在堆区上面的,外面操作动态内存的,malloc free calloc realloc 也都是对堆区的内存进行操作。

malloc 开辟空间 free 释放空间

malloc

malloc 是C语言提供的动态内存开辟函数。

viod* malloc(size_t size);

malloc 申请的是连续的空间。如果开辟成功,那么返回的就是开辟的内存的起始地址。如果开辟失败,就返回 NULL 。返回值的类型是 void* 因为 malloc 不知道开辟的内存是什么类型。所以我们使用的时候,可以强制类型转换一下。转换为我们要使用的类型。例如:我们开辟整型内存。

int* p = (int*)malloc(10*sizeof(int));

free

free 就是对开辟的堆区空间进行释放。每次 free 释放内存之后,一定要把指针变量置为 NULL 防止出现野指针。用法如下:

int* p = (int*)malloc(10*sizeof(int));
free(p);
p = NULL;

使用一个变量来开辟空间,这里使用一个变量 num 来开辟一段动态空间:

int main()
{
	int num = 0;
	scanf("%d", &num);
	int* ptr = (int*)malloc(num * sizeof(int));
	if (ptr != NULL)
	{
		int i = 0;
		for (i = 0; i < num; i++)
		{
			*(ptr + i) = i + 1;
		}
		for (i = 0; i < num; i++)
		{
			printf("%d ", *(ptr + i));
		}
	}
	free(ptr);
	ptr = NULL;
	return 0;
}

在这里插入图片描述
这里就是通过输入一个数 num 然后开辟相应的内存空间。并且赋值为 1 - 10 。

calloc 开辟空间

C语言也提供了另外一个开辟空间的函数,calloc 与 malloc 不同的是,calloc 开辟空间之后,在返回空间的起始地址之前,把所有空间全部赋值为 0 。示例:

//C语言文档给的代码
void* calloc (void* ptr, size_t size);
int main()
{
	int* p = (int*)calloc(10, sizeof(int));
	if (NULL != p)
	{
		//使用空间
	}
	free(p);
	p = NULL;
	return 0;
}

在这里插入图片描述
在这里插入图片描述
由第二张图片就可以看到,p 所指向的空间,全部被置为了 0 。如果我们对申请的内存有初始化的需求,就可以使用 calloc 来进行初始化。

realloc 管理内存

有时候我们会发现申请的内存大了或者小了,所以就用到 realloc 来对内存大小进行灵活的调整。如果 realloc 调整内存失败后,也会返回空指针。C语言给的函数模型是这样:

void* realloc (void* ptr, size_t size);

ptr 是要调整的内存地址。
size 是要调整的大小。
返回值是调整大小之后的内存起始位置。

realloc 调整内存的两种情况

情况1:原有空间之后有足够大的空间

当原来的空间后面有足够大的空间的话,就连着原有空间继续开辟,就是下面图片这样的情况。就是原有内存之后直接追加空间,原来空间的数据不发生变化,并且返回值的地址还是原来的地址。
在这里插入图片描述

原有空间之后没有足够大的空间

当原来空间的后面没有足够大的空间的话,其扩展的方法就是:再找一块空间,可以放得下原有的空间的内容和新开辟的空间,并且返回新的内存地址。不过在传回新的地址之前。会把原来的那段空间 free 掉。不能用原来的指针去接收返回值,因为如果开辟失败,那么原来的指针也变成 NULL 了。就是下图这样:
在这里插入图片描述

realloc 使用代码示例

int main()
{
	int* p = (int*)calloc(10, sizeof(int));
	//空间不够 增加到 20个 int
	int* ptr = (int*)realloc(p, 20 * sizeof(int));
	if (ptr != NULL)
	{
		p = ptr;
	}
	else
	{
		//ptr是空指针 返回-1
		return -1;
	}
	//增容成功
	for (int i = 10; i < 20; i++)
	{
		*(ptr + i) = i;
	}
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", *(ptr + i));
	}
	free(ptr);
	ptr = NULL;
	free(p);
	p = NULL;
	return 0;
}
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Lockey-s

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

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

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

打赏作者

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

抵扣说明:

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

余额充值