动态内存申请

本文详细介绍了C语言中动态内存申请函数malloc、calloc、realloc的使用方法,以及free函数的释放机制,强调了正确处理内存分配和释放的重要性,包括避免常见错误如未判断返回值、越界访问和误释放非动态内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、为啥要申请动态内存?

二、内存申请函数

申明一下:(头文件  )

1、malloc函数:

2、calloc函数:

3、realloc函数: 

4、free函数:

5、代码实现一下: 

说一下,因为1-3的函数都要有的

malloc:

calloc:

realloc:

三、常见错误:

1、未判断返回值(没有判断是否成功)

2、对动态开辟的空间进行越界访问

3、对非动态开辟的地址用free进行释放


一、为啥要申请动态内存?

我们了解学过的:

各种类型变量的声明,数组的声明,再创建时都是会申请一定的空间(内存),但是都是在栈区上申请

第一个 向栈区申请4个字节的空间

第二个 向栈区申请5*4 = 20个字节的空间

 但是,这样在栈上申请开辟的空间大小是固定的,然而数组在声明时必须确定大小,这样限制了数组只能这么大,后续需要更大的空间时,无法满足这一个要求;(当然提一嘴,🐸🐸c99支持了变长数组,也就是说数组里面的元素个数可以是变量,遗憾的是VS不支持🤷‍♂️🤷‍♂️)

可是,有时候我们需要的空间⼤⼩在程序运⾏的时候才能知道,这个时候怎么办呢???就此就有了动态内存的申请的用武之地可以让程序员灵活开辟和销毁空间。

二、内存申请函数

申明一下:(头文件  <stdlib.h>)

        有关内存的情况,都是以字节为单位进行的,所以下面的空间申请也是以字节为单位向内存申请空间,而下面向内存申请的一块空间是连续的,有没有发现和数组很像??其实类似于数组,但是数组向栈区申请固定空间,然而内存函数就是向内存申请一个可变化大小的空间,但是不同内存函数之间又有着不小的差别  


1、malloc函数:

 向内存申请⼀块连续可⽤的空间,并返回指向这块空间的指针其中size是元素大小;但是返回viod指针,所以可以为各种类型数据申请空间,自己去定义需要的类型,但是需要用个强制内型转换

以char型为例:相当于申请一个char型数组arr[5];(前面乘了5就是申请5个size(type)大小的元素)

 如下图:向内存申请一块空间;

 返回的是指针

失败则是返回空指针(NULL)

成功指向开辟好空间的指针

如果参数 size 为0malloc的⾏为标准是未定义的,取决于编译器

2、calloc函数:

向空间申请num个大小为size元素( 也就是一个数组),并把每个字节初始化为 0

一个字节:


3、realloc函数: 

让空间申请更加灵活,可以修改空间的大小,返回的是调整之后的起始位置;str接受需要调整内存的地址size需要调整空间大小,也就是你原本空间是20,你需要40字节的空间,那么你就申请40,他会给你的空间从20字节的空间40字节的空间

申请成功的话,调整空间有2种情况:

情况1: 直接原地址扩容

情况2:拷贝原地址内容到新地址扩容空间大小——异地扩容

!!!!异地扩容会将原空间进行销毁

有一个写法:这个相当于上面malloc的例子,传的空地址,此时相当于向内存申请一个空间来使用,而不是调整一个空间大小,等价于malloc

失败则是返回空指针(NULL)

成功指向开辟好空间的指针

如果参数 size 为0malloc(realloc)的⾏为是标准是未定义的,取决于编译器


4、free函数:

动态内存的释放和回收,未释放可能存在内存的泄露    "内存泄露"

释放的是起始位置,注意一定要传起始地址(我们申请空间下来,我们拥有了这个空间是使用权限你只有使用权限,肯定是要还回去的,住酒店到时间了还得退房;free相当与将使用权限 还给操作系统)

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏为是未定义的。(不能释放非动态开辟空间)
  • 如果参数 ptr 是NULL指针,则函数什么事都不做

回收权限以后,接受动态内存的指针会变成野狗(野指针),我们要给它栓起来(赋值空指针 )

 注意:虽然若是没有释放,当程序结束时会由操作系统进行释放,但是还是要尽量去使用free释放,我们要告诉别人需要释放,因为你不退出,这个内存一直占着茅坑不拉屎,不是浪费资源么,所以一定要去释放!!!!!!


5、代码实现一下: 

说一下,malloc 、calloc、realloc函数都要有的操作步骤

你申请了空间,有可能会失败,若是失败呢就是空指针,对于空指针是不能进行操作的,所以需要判断一下是否为空!!!看下面代码即可;

malloc:

int main()
{
	char* arr = (char*)malloc(5*sizeof(char));
	if (arr == NULL)
	{
		perror("malloc");
		return 1;
	}
	free(arr);
	arr = NULL;

	return 0;
}

 return 1:表示提前结束的意思,你都申请失败了那么我们就只好提前结束了

perror函数:用于在发生系统调用错误时输出有关错误信息的描述。


calloc:

int main()
{
	char* arr = (char*)calloc(5,sizeof(char));
	if (arr == NULL)
	{
		perror("calloc");
		return 1;
	}
	free(arr);
	arr = NULL;

	return 0;
}

realloc:

int main()
{
	char* arr = (char*)calloc(5, sizeof(char));
	if (arr == NULL)
	{
		perror("calloc");
		return 1;
	}
	//arr要是首元素地址,额外创建一个指针来接受realloc,因为如果realloc申请失败,则会返回空指针,但是arr是有值的
	char* ctr = realloc(arr, 10 * sizeof(char));
	if (ctr == NULL)
	{
		perror("realloc");
		return 1;
	}
	arr = ctr;
	//释放空间
	free(arr);
	arr = NULL;
	return 0;
}

三、常见错误:

1、未判断返回值(没有判断是否成功)

2、对动态开辟的空间进行越界访问

3、对非动态开辟的地址用free进行释放

注意:👉free 释放一个NULL什么也不发生,不属于动态内存的错误!!✨

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值