C语言---动态内存管理

发布于:2025-07-20 ⋅ 阅读:(19) ⋅ 点赞:(0)

为什么要有动态内存分配

        我们在学习动态内存管理之前,一直都是通过开辟变量,或者是开辟数组的方式来在内存的栈区开辟空间的,但是这样的开辟方式有局限性,因为一旦开辟之后,它们的大小就无法改变,就缺少了很多的灵活性,但是动态内存管理就可以帮助我们解决这个问题,它是在堆区开辟空间的,并且它所开辟的空间是可大可小的。

动态内存开辟四大函数

        其实想要动态开辟内存空间非常的简单,我们只需要学会内存开辟四大函数就可以了。

        malloc和free

        malloc函数就是用来在内存的堆区开辟空间的,它的函数定义如下。

   void* malloc (size_t size);

   函数的形参表示所要开辟空间的字节大小,你想要开辟几个字节的空间,就给形参什么值,malloc函数是在堆区开辟的一块连续的空间,一旦开辟了空间,我们想要找到这块空间,就势必要只要它的起始地址值,而malloc函数的返回值就是这个作用,它返回的是开辟空间的起始地址,那为什么是void*类型的指针呢?原因就是我在开辟的时候,我也不知道要往这块空间里边存放什么类型的数据,或者说什么类型的数据都可以存放在我这块空间里边,所以一开始就给它返回的是void*类型的指针。还有一个值得注意的点就是malloc开辟空间如果失败的话,就会返回NULL值,所以我们需要对返回值进行判断。

        malloc函数的使用举例

#include<stdio.h>
#include<stdlib.h>//四大内存开辟函数都需要包含这个头文件

int main()
{
	//假设现在我想要开辟40个字节的空间,并且像里边存放整型数据
	int* pi = (int*)malloc(40);
	//判断是否开辟成功
	//为NULL就代表开辟空间失败,perror打印开辟失败的原因
	//返回非0的值,C语言里边返回非0的值表示异常结束
	if (pi == NULL)
	{
		perror("malloc");
		return 1;
	}
	//开辟成功,可以向这块空间里边存值
	for (int i = 0; i < 10; i++)
	{
		*(pi + i) = i + 1;//存入1~10的值
	}
	//打印
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(pi + i));
	}

	return 0;
}

        由上边的代码跟运行结果来看,好像似乎并没有什么问题,但malloc毕竟是动态开辟的空间,开辟了空间难道就不用回收的吗?答案是要回收的,上边的代码好像并没有回收,那怎么也可以运行呢,原因是当程序结束的时候,操作系统会自动帮你回收,不过如果日后的代码过长,或者是程序是一个7*24小时不停歇的运转的话,如果我们不主动回收,就会出现内存泄露的问题,所以如果这块动态开辟的内存你不再想要使用的时候,就请主动回收掉,free函数就是用来主动回收的。

        free:

   它的函数定义如下

   void free (void* ptr);

   它的形参的指针就指向的是动态开辟的起始地址的位置,如果给它传NULL,那么这个函数将什么都不会做。

   接下来我们对刚才的代码做一个完善   

        由图可见,释放代码其实就两行,但是至关重要。

        大家可能会有疑惑,释放完了空间之后,为什么还要将pi赋值为NULL指针,原因是因为刚才的pi指针接收了malloc动态开辟的空间,但是当free之后,刚才申请的那块空间已经被释放了,里边的数据也已经不是刚才存进去的数据了,而此时pi指针里边仍存放着那块空间的地址,这就形成了野指针,所以给它赋值为NULL。

        calloc和realloc

        calloc函数也是用来动态内存开辟空间的函数,它的函数定义如下

   void* calloc (size_t num,size_t size);

   函数的形参的意思就是为num个大小为size的元素开辟空间,并且calloc函数会把开辟的空间的每个字节都初始化为0。

        calloc函数的使用举例

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//给10个大小为int类型的数据开辟空间
	//用malloc函数就相当于
	//malloc(10 * sizeof(int));
	int* pi = (int*)calloc(10, sizeof(int));
	if (pi == NULL)
	{
		perror("calloc");
		return 1;
	}

	//开辟成功,使用
	//calloc会自动的给申请的空间初始化为0
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(pi + i));
	}

	//释放
	free(pi);
	pi = NULL;

	return 0;
}

        realloc函数是用来对我们动态申请的内存进行调整的。它的函数定义如下。

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

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

        对于realloc函数的重新调整空间大小,总共有三种情况。

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

        情况2:原有的空间之后没有足够的空间。

        情况3:重新调整空间失败,返回NULL指针。

        realloc函数的使用举例

#include<stdio.h>
#include<stdlib.h>
int main()
{
	//申请空间
	int* pi = (int*)malloc(40);
	if (pi == NULL)
	{
		perror("malloc");
		return 1;
	}
	//使用空间
	for (int i = 0; i < 10; i++)
	{
		*(pi + i) = i++;
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(pi + i));
	}
	//内存不够,重新调整
	//注意,这个返回值不能用刚才的pi来接收,因为可能开辟空间失败返回NULL,这样就导致原来开辟的空间也找不到了。
	int* ptr = (int*)realloc(pi, 80);
	if (ptr == NULL)
	{
		perror("realloc");
		return 1;
	}
	else//开辟成功
	{
		pi = ptr;
		ptr = NULL;
	}
	//继续使用........

	//释放空间
	free(pi);
	pi = NULL;
	return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到