【动态内存开辟】malloc(),calloc(),realloc(),free(),堆区的动态内存申请

本文详细介绍了C语言中动态内存管理的关键函数malloc(),free(),calloc(),realloc(),包括它们的用途、原型、参数和注意事项,强调了及时释放动态内存以防止内存泄漏的重要性。
摘要由CSDN通过智能技术生成

本文主要介绍了C语言中动态开辟内存的相关函数。



一、动态内存开辟是什么?

例如:

int a = 10;//在栈空间上开辟4个字节空间
char arr[20] = {0};//在栈空间上开辟20个字节的连续空间

上述是我们之前为变量开辟空间的方式。计算机中内存分为几个区,栈区,堆区,静态区,我们使用动态内存函数开辟的空间存放在堆区。
malloc(), calloc(), realloc(),free()等都是动态内存函数。

那么接下来,本文将介绍如何使用动态内存函数。

在这里插入图片描述

二、动态内存函数

头文件:#include <stdlib.h>

2.1 malloc()函数

介绍:动态开辟 size 字节大小的空间。
【函数原型】:void* malloc (size_t size);
【参数】:size 表示需要动态开辟内存的大小,单位:字节。
【返回值】:void* 类型的指针,返回动态开辟空间的起始地址。

由于计算机不知道程序员申请size大小的空间是干什么用的,所以返回void* 类型的指针,由程序员自行决定。程序员使用强制类型转换,使开辟的空间转换成自己需要的空间类型。

【如何使用?】

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//动态开辟40字节大小的空间
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("动态开辟空间失败:");
	}
	else 
	{
		//赋值
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}

		//打印
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	free(p);//释放空间,防止内存泄漏
	p=NULL;//避免野指针出现
	
	return 0;
}

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

  • 10 * sizeof(int):表示malloc()函数动态开辟10个int类型的空间大小。
  • (int*):表示强制类型转化,将malloc()返回的地址转换成自己需要类型的地址。
  • 使用int* 类型的指针接收

注意:malloc()函数可能会开辟内存失败,因此,我们在使用malloc()函数开辟的空间之前,要先检验其有效性。如果返回值为空指针,表示动态开辟空间失败,后面无法对指针p进行相关操作,如果不为空表示开辟空间成功,可以对这块空间进行操作。

2.2 free()函数

介绍: 释放由malloc(), calloc(), realloc()动态开辟的空间,防止内存泄露。
【函数原型】:void free (void* ptr);
【参数】:void*ptr,任意类型的指针,指针指向需要释放空间的起始地址。
【返回值】:无返回值。

注意:free() 函数只能释放动态开辟的内存空间,否则报错。

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//动态开辟10个整型大小的空间
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("动态开辟空间失败:");
	}
	else
	{
		free(p);//释放空间
		p = NULL;//编程好习惯,释放空间后,立即把指针置空,防止野指针的出现
	}

	return 0;
}

2.3 calloc() 函数

介绍: 动态开辟num个size大小的空间,并把每个字节都初始化成0。
【函数原型】:void* calloc (size_t num, size_t size);
【参数】:2个参数。num 表示需要开辟元素的个数,size 表示每个元素的大小,单位:字节。
【返回值】:void* 类型的指针,返回动态开辟空间的起始地址。

注意:calloc() 和 malloc() 函数的区别在于,calloc()函数对动态开辟的空间进行了初始化,把每个字节都初始化成0。

【函数使用】:和malloc()函数使用一致, 开辟空间后需要先判断是否开辟成功,开辟成功后再使用。

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//malloc()动态开辟10个整型大小的空间
	int* p1 = (int*)malloc(10 * sizeof(int));
	if (p1 == NULL)
	{
		perror("动态开辟空间失败:");
	}

	//calloc()动态开辟10个整型大小的空间
	int* p2 = (int*)calloc(10, sizeof(int));
	if (p2 == NULL)
	{
		perror("动态开辟空间失败:");
	}

	free(p1);//释放空间
	p1 = NULL;//编程好习惯,释放空间后,立即把指针置空,防止野指针的出现

	free(p2);
	p2 = NULL;

	return 0;
}

接下来我来带大家看一下,malloc()和calloc()函数开辟空间的内存。

在这里插入图片描述

我们发现malloc()函数开辟的空间,内存中都是随机值,而calloc()函数开辟的空间,内存中全部为0。说明calloc()函数开辟空间时,会将开辟的空间每个字节全部初始化为0。这也是calloc()和malloc()函数的唯一区别,除此之外,malloc()和calloc()函数功能一致。

2.4 realloc()函数

介绍: 对动态开辟的空间进行调整。可以调大,也可以调小。
【函数原型】:void* realloc (void* ptr, size_t size);
【参数】:2个参数。void* ptr 表示需要调整空间的起始地址。size 表示调整之后的空间大小,单位:字节。
【返回值】:void* 类型的指针,返回调整之后的动态开辟空间的起始地址。

注意:
realloc()函数,将空间调大时,有两种情况:

  • 如果需要进行调整的空间 ptr 之后有足够大的空间,则直接在ptr后面扩大空间,返回这块空间原来的起始地址ptr。
  • 如果需要进行调整的空间 ptr 之后的空间不足,则realloc()函数将从堆区的其他地方开辟size大小的空间,并将原地址空间 ptr 的数据拷贝到新空间ptr2中, 释放原起始地址(free(ptr),返回新的起始地址ptr2。

【函数使用】
【情况1:】待调整空间之后,有足够大的空间。

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//malloc()动态开辟10个整型大小的空间
	int* p1 = (int*)malloc(10 * sizeof(int));
	if (p1 == NULL)
	{
		perror("动态开辟空间失败:");
	}

	//扩大p1空间, 使空间大小为80个字节 -- 20 * sizeof(int)
	int* tmp = (int*)realloc(p1, 20 * sizeof(int));
	if (tmp == NULL)
	{
		perror("realloc fail:");
	}
	else
	{
		p1 = tmp; //将扩大后的空间赋值给p1
		free(p1);//释放空间
		p1 = NULL;//编程好习惯,释放空间后,立即把指针置空,防止野指针的出现
	}

	return 0;
}

在这里插入图片描述

【情况2:】待调整空间之后,空间不足。

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//malloc()动态开辟10个整型大小的空间
	int* p1 = (int*)malloc(10 * sizeof(int));
	if (p1 == NULL)
	{
		perror("动态开辟空间失败:");
		exit(-1);
	}

	//扩大p1空间, 使空间大小为 9999* sizeof(int) 字节
	int* tmp = (int*)realloc(p1, 9999 * sizeof(int));
	if (tmp == NULL)
	{
		perror("realloc fail:");
		exit(-1);
	}
	else
	{
		打印,验证是否realloc()成功之后是否free()了原地址
		//int i = 0;
		//for (i = 0; i < 10; i++)
		//{
		//	printf("%d ", *(p + i)); //编译器报错
		//}
		
		p1 = tmp; //将扩大后的空间赋值给p1
		free(p1);//释放空间
		p1 = NULL;//编程好习惯,释放空间后,立即把指针置空,防止野指针的出现
		tmp = NULL;
	}

	return 0;
}

【这里显示:realloc()从堆区其他地方,开辟size大小空间】

由内存图观察到,p1 和 tmp 的地址值不同。说明p1之后有其他数据,不能直接在后面扩大空间,需要在堆区另外找一块size大小内存,并将原空间p1的数据拷贝到新空间tmp,释放原空间p1,并返回新开辟空间tmp的起始地址

在这里插入图片描述

结语

理解malloc(),calloc(),realloc(),free()函数的使用,理解他们开辟空间的过程,以及动态开辟空间如果不再使用,要及时free()掉,防止内存泄漏。
希望以上可以帮助到大家~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值