ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

【C语言】动态内存分配

2021-09-07 11:02:17  阅读:266  来源: 互联网

标签:malloc 函数 int realloc free C语言 动态内存 空间 分配


目录

动态内存分配存在的原因

首先我们知道内存开辟的方式有:

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

上述的两种方式有两个特点:
1)空间开辟的大小是固定的
2)数组在声明时需要明确其大小,即数组长度,其内存在编译时分配。
但是在实际应用中我们所需要的不止是一个固定大小的数组,而常常需要堆数组的长度进行修改,而数组在编译时开辟空间的方式就不能满足我们的需求了,这时我们就需要用到动态内存分配了。

动态内存函数

我们常用的动态内存函数有malloc,free,calloc,realloc等等

1. malloc 和 free

C语言给出了这么一个动态内存开辟的函数:

void* malloc (size_t size);

这个函数会向内存申请一块连续可用的空间,同时返回指向这块空间的指针。
在这里我们来了解一下内存的大致分布:内存分为栈,堆,静态区等等部分。其中栈是临时变量所存储的空间,同时函数开辟空间时也是在栈中进行的,这被称为函数栈帧,有机会的话后面会介绍的;堆就是动态内存开辟时所申请的空间;而静态区是静态变量开辟时所申请的空间,比如全局变量,static修饰的变量等。在这里插入图片描述

而malloc函数向内存申请空间就是在堆申请的。
malloc函数在申请空间时会有两种情况:
1)若空间开辟成功,则返回指向该空间的指针。
2)若空间不足,开辟失败,则返回NULL。
而函数的返回值为void* ,是因为malloc在开辟空间时并不知道所要开辟空间的类型,在具体使用时使用者需要自己决定;其次,若size为0,malloc的行为是标准未定义的,具体取决于编译器。
与malloc相对的,C语言提供了另外一个函数free,是专门用来做动态内存的释放和回收的,其函数原型如下:

void free (void* ptr);

对于free函数有两点需要注意:
1)若所free的指针不是指向动态开辟的空间,那么free的行为是标准未定义的。
2)若所free的指针是NULL,则什么也不会发生。
malloc和free都声明在<stdlib.h>头文件中。
需要注意的是malloc和free通常是成对使用的,否则会造成内存泄露。
举个例子:

int main()
{
	int* a = (int*)malloc(sizeof(int) * 10);//向内存申请10个int字节的连续空间
	if (a == NULL)//判断内存申请是否成功
	{
		printf("malloc fail");
		exit(-1);
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		a[i] = i;
	}
	free(a);//释放a所指向的内存空间
	a = NULL;//free函数并不会将a置空,那么此时a为野指针,需要我们手动置空
	return 0;
}

2. calloc

C语言同时还提供了calloc函数来实现动态内存分配,其函数原型为:

void* calloc (size_t num, size_t size);

calloc函数的功能是向内存申请num个size大小的连续空间,并在申请的同时将这些空间初始化为0;与malloc不同的是calloc会在返回地址之前将申请的空间中的每个字节初始化为0,也就是说若我们在申请空间时需要初始化所申请的空间,calloc可以方便我们的操作。比如:

`int main()
{
	int* a = (int*)calloc(10, sizeof(int));
	if (a == NULL)
	{
		printf("calloc fail");
		exit(-1);
	}
	free(a);
	a = NULL;
	return 0;
}`

在这个函数中,calloc向内存申请空间后的连续40个字节空间内容均被初始化为0。
在这里插入图片描述

3.realloc

从功能上将上述的malloc和calloc函数都并未实现可以是内存动态改变的功能,它们都只是向内存申请了一片固定的空间,而实际上想要真正对内存进行动态的调整就需要realloc函数,其函数原型为:

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

参数中的ptr为要调整的内存空间的起始地址;size为调整后空间的新大小;
函数的返回值为调整后的空间的起始地址。
函数在调整内存空间时,有可能会将原内存空间的内容转移到新的内存空间上,这就与realloc调整空间可能出现的两种情况有关:
1)原内存空间后的空间足够大,足以调整。
2)原内存空间后没有足够的空间,不足以开辟所需要的空间。在这里插入图片描述
由于上述两种情况的存在,realloc在具体使用过程中需要注意一些:

int main()
{
	int* a = (int*)malloc(sizeof(int) * 10);//向内存申请40个字节的连续空间
	if (a == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	int* tmp = (int*)realloc(a, sizeof(int) * 20);//调整原空间使其扩大为80个字节
	if (tmp == NULL)
	{
		printf("realloc fail");
		exit(-1);
	}
	a = tmp;
	free(a);
	a = NULL;
	return 0;
}

上述程序中的tmp是必要的,这是因为如果原内存后没有足够大的空间,那么若代码改为a = (int*)realloc(a,sizeof(int)*20);a在realloc函数执行过程中会改变指向,致使realloc找不到原内存,从而无法将原内存空间的数据拷贝到新开辟的内存空间中,导致数据丢失,因此需要用一个临时变量来记录新开辟的内存空间,在修改原指针。
另外一点,若realloc中的ptr参数为NULL,那么realloc函数就和malloc函数的功能一样了。

标签:malloc,函数,int,realloc,free,C语言,动态内存,空间,分配
来源: https://blog.csdn.net/love_guanghui/article/details/120147060

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有