【C语言】内存操作篇---动态内存管理----malloc,realloc,calloc和free的用法【图文详解】

欢迎来CILMY23的博客喔,本篇为【C语言】内存操作篇---动态内存管理----malloc,realloc,calloc和free的用法【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注+收藏。

前言

 在学完结构体后(结构体1:http://t.csdnimg.cn/ZkBHj结构体2:http://t.csdnimg.cn/rmAwJ)我们要进入新篇章了,内存操作中最关键的一节---动态内存管理,本篇博客将了解malloc,realloc,calloc和free的用法。

目录

一、为什么会有动态内存管理?

二、malloc和free

malloc的介绍和使用  

空间回收 

free的介绍和使用

三、realloc

realloc的介绍和使用 

四、calloc 

calloc的介绍和使用 


一、为什么会有动态内存管理?

 在过去我们向内存中申请空间有两种方式,一是创建变量,二是创建数组

#include<stdio.h>

int main()
{
	int C = 23;//申请四个字节空间
	char c = 'C';//申请1个字节空间
	char CI[10] = "CILMY23";//申请10个字节空间
	return 0;
}

但是上述的开辟空间的方式有两个特点:
•    空间开辟大小是固定的。
•    数组在声明的时候,必须指定数组的长度,数组空间一旦确定了大小不能调整
我们申请的空间都很固定,没法灵活调整,但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组和变量的编译时开辟空间的方式就不能满足了。
C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,就比较灵活了。 

二、malloc和free

malloc可以在cplusplus网站查询:malloc - C++ Reference (cplusplus.com)  

 malloc函数原型如下:

void* malloc (size_t size);

 malloc的函数介绍如下:

malloc 的功能如下:

malloc的介绍和使用  

malloc函数是头文件stdlib中的,malloc函数是用来向内存申请空间的(在堆区申请),在函数原型中我们可以看到有一个形参size_t size,根据Allocates a block of size bytes of memory, returning a pointer to the beginning of the block,我们知道这个形参是计算空间大小后得出的结果,比如申请40个字节空间,size就等于40.那它最后会返回一个指针,指向这个空间的起始位置,那返回类型是void*,因为我并不知道这段空间会干什么,所以返回void*(不懂可以看http://t.csdnimg.cn/dshm8),当malloc失败后,会返回一个NULL。

使用如下:

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

int main()
{
	// 向内存空间申请40个字节
	//将void*转换成int*类型将其存入指针变量p
	int* p = (int *)malloc(10 * sizeof(int));

	int i = 0;
	//将i存入开辟的空间
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//将空间中的数值打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
}

结果如下:

 

 图解如下:

 那如果我们申请失败了呢?那我们就可以用perror来直接打印错误信息。

if (*p == NULL)
{
	perror("malloc");
}

空间回收 

malloc是在堆区申请空间的,malloc的空间回收有两种方法,一是free回收,二是程序结束的时候,由操作系统回收 我们这里主要讲free回收,首先回顾一下内存的区域,主要由堆区栈区和静态区构成,堆区是动态分配区,像malloc这些,栈区是临时的参数,局部变量和形式参数,静态区主要是全局变量和静态变量。

 
     

free的介绍和使用

free函数的原型如下:

void free (void* ptr);

free函数介绍如下:

 free的功能和使用案例如下:

free函数是用来释放动态开辟出来的空间,给到地址就能释放地址所指向的位置 

free的使用:

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

int main()
{
	// 向内存空间申请40个字节
	//将void*转换成int*类型将其存入指针变量p
	int* p = (int *)malloc(10 * sizeof(int));

	if (*p == NULL)
	{
		perror("malloc");
	}
	int i = 0;
	//将i存入开辟的空间
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	//将空间中的数值打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	free(p);
	p = NULL;
}

我们使用free(),因为我们将p所指向的空间释放了,那p就成了野指针,我们就需要处理野指针,所以将p置空。 

总结:

malloc如果开辟成功,则返回⼀个指向开辟好空间的指针。
•    如果开辟失败,则返回⼀个NULL 指针,因此malloc的返回值⼀定要做检查。
•    返回值的类型是void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
•    如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

free函数只能用来释放动态开辟的内存。
• 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
• 如果参数 ptr 是NULL指针,则函数什么事都不做。

三、realloc

 

 realloc函数可以在cplusplus网站查询:realloc - C++ Reference (cplusplus.com)

realloc的原型如下:

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

realloc的函数介绍如下:  

realloc的功能和使用案例如下: 

realloc的介绍和使用 

 realloc的参数有void* ptr, size_t size,size就是要调整后的空间大小,ptr则是要调整的空间起始地址。realloc 的调整分两种情况,一种是原地扩,也就是后面的空间足够,如下图所示,未分配的空间加已分配的橙色空间刚好够size,或者小于size,则realloc原地扩

第二种情况是未分配的黑色空间加已分配的橙色空间,超过size后的字节,那realloc会到新的一块未分配区域重新开辟一块空间,来分配原先的字节,并将原来的地址做拷贝,最后返回新的空间地址,并且旧空间会自动释放掉。

realloc的使用:

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

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

	int i = 0;

	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	//调整申请的堆上内存
	int* tmp = (int*)realloc(p, 40);
	if (tmp != NULL)
	{
		p = tmp;
		tmp = NULL;
	}
	else
	{
		perror("realloc");
	}

	free(p);
	p = NULL;

	return 0;
}

总结:

• ptr 是要调整的内存地址
• size 调整之后新大小
• 返回值为调整之后的内存起始位置。
• 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。
•    realloc在调整内存空间的是存在两种情况:
◦ 情况1:原有空间之后有足够大的空间
◦ 情况2:原有空间之后没有足够大的空间

四、calloc 

calloc函数可以在cplusplus网站查询:calloc - C++ Reference (cplusplus.com) 

calloc的原型如下:

void* calloc (size_t num, size_t size);

calloc的函数介绍如下: 

 

calloc的功能和使用案例如下: 

 

calloc的介绍和使用 

calloc的参数是两个,一个是num,一个是大小size,其中一个给数量,一个给大小。calloc和malloc函数最大区别就是,calloc会赋一个初值,每个初值都是0. 使用和malloc是差不多的

 

使用如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int* p = (int*)calloc(10 ,sizeof(int) );

	int i = 0;

	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}

	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}

	free(p);
	p = NULL;
}

 结果如下:

 

 如果我们只是想开辟空间,我们只需要用malloc,而calloc是把开辟出来的空间赋了一个初值。

总结:

•  函数的功能是为num 个大小为size的元素开辟⼀块空间,并且把空间的每个字节初始化为0
•  与函数malloc 的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全 0

感谢各位同伴的支持,本期动态内存管理篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。    

  • 22
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值