动态内存的使用之malloc,free,calloc,realloc

目录

1.为什么要使用动态内存

2.什么是内存的动态分配

3.动态内存函数之一malloc

4.动态内存函数之一free

5.动态内存韩式之一calloc

6.动态内存函数之一realloc

7.常见动态内存函数的错误


1.为什么要使用动态内存

Int arr[20]={0};

Int va=10;

像上面方式开辟内存空间的时候,开辟空间的大小是固定的,且数组在申明的时候需要指定数组的长度。例如:在存储一个班同学的身高的时候,往往不知道班级人数的情况,我们会估计一个相对合理的值来开辟空间的大小。如果开辟的空间大了就会造成浪费,小了可能会造成数据的丢失。开辟的内存空间的大小往往和认为输入数据有关。为了改善上述问题,就需要,开辟动态内存来进行改善


2.什么是内存的动态分配

当我们创建变量的时候,全局变量存放在静态存储区,局部变量(包括形参)存放在动态存储区中,这个存储区称为栈。

除了栈区,还有堆区,用来存放一些临时数据的内存动态分配区域,需要的时候开辟,不需要的时候就释放,使用起来比较灵活,但只能通过指针来引用。


3.动态内存函数之一malloc

malloc函数在C语言提供的一个开辟连续动态内存的函数,在stdlib.h中进行声明。

一般形式void* malloc(unsigned int size)

作用:在动态内存中开辟一个长度为size连续空间

返回值:第一个字节的地址。

:1.size为无符号整型,是需要开辟的内存的字节数,当size为0时,malloc的行为是标准未定义的,取决于编译器,且开辟的空间是不会进行初始化的。

       2.指针的基类型是void*,不指向任何确定类型数据(纯地址),只提供一个地址,需要在使用的时候由使用者自行确定,如:int* pt=(int*)malloc(100);

       3.若不能成功开辟空间,则返回空指针(NULL),因此每次都检测通过malloc返回的指针是必要的,确保它不是空指针。


4.动态内存函数之一free

一般形式void free(void* p)

作用:函数free在stdlib.h中声明,释放指针变量p所指向的动态空间,p是最近一次调用malloc函数或者callloc函数的返回值。

返回值:无

:当free的参数是NULL时,是没有任何效果的。


5.动态内存韩式之一calloc

开辟动态内存时方法除了malloc外,C语言还提供了一个函数叫做calloc,原型如下:

一般形式void* calloc(unsigned n,unsigned size)

作用在动态内存中开辟n个长度为size连续空间

返回值:所分配域的起始位置指针,若请求失败,返回NULL。

:与malloc有一个很大的不同是,calloc会对分配的内存初始化为零。

其中:nitems是要分配的元素个数,size是元素的大小。当请求失败的时候,则返回NULL。


6.动态内存函数之一realloc

当开辟的空间过大、或过小,需要对开辟的动态内存空间进行调整,让内存管理更加灵活的时候,就可以尝试使用realloc函数了,函数原型如下:

一般形式:void *realloc( void *memblock, size_t size );

作用:将memblock所指向的动态空间重新分配为大小为size的动态空间。

其中:memblock 要调整的地址的内存其实位置,size是重新调整之后新的大小,返回值为调整后的内存的起始位置。如果分配失败则,返回空指针NULL

:当需要“扩大”动态空间的时候,如果原内存空间后方有足够的空间,能满足分配额外内存的要求时,自然天下太平,在原内存空间后面直接分配就好。但是,当原空间后方的连续空间不足的时候,那就需要从堆上另外找一块size大小的内存,并且把原空间的内容复制到新的大小为size的空间中,返回新的指针(数据被移动了的)。原内存地址的指针就成了悬挂指针,即指针指向了一块没有分配给用户使用的内存


下面通过一个例子来进行加深,理解。

问题描述:

输入5个人的成绩,并输入其中不及格(小于60分)的成绩。

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
/*练习:建立动态数组,存储5个学生成绩,并将不合格学生成绩输出*/
int main()
{
	void check(int*);
	int* p1 = (int*)malloc(5 * sizeof(int)); //开辟动态内存空间,并地址转化成int* 型,存放值指针变量p1中
	if (p1 == NULL)//检验内存是否开辟成功
	{
		printf("内存空间开辟失败\n");
	}
	//输入5个学生成绩
	printf("请输入5个学生的成绩:\n");
	for (int i = 0; i < 5; i++)
	{
		scanf("%d", p1 + i);
	}
	//检查是否合格
	check(p1);
	free(p1);//释放内存空间
	p1 = NULL;//将改指针置空
	return 0;
}

void check(int* str)
{
	printf("不合格的学生成绩是:");
	for (int i = 0; i < 5; i++)
	{
		if (*(str + i) < 60)
		{
			printf("%d  ", str[i]);
		}
	}
	printf("\n");
}

7.常见动态内存函数的错误

对NULL指针的解引用操作

void test()
{
	int* p = (int*)malloc(100);
	*p = 20;//如果内存开辟失败,p的值是NULL,就会出问题
	free(p);
}

对动态开辟空间的越界访问

void test()
{
	int* p = (int*)malloc(5*sizeof(int));
	if (p == NULL)
	{
		printf("err");
	}
	for (int i = 0; i <= 5; i++)
	{
		*(p + i) = i;//当i是5的时候越界访问
	}
	free(p);
}

对非动态开辟内存使用free释放

int test()
{
	int a = 10;
	int* p = &a;
	free(p);//不行的
}

使用free释放一块动态开辟内存的一部分

int test()
{
	int* p = (int*)malloc(100);
	p++;//此时p不在指向p
	free(p);//不能只释放动态内存的一部分
}

对同一块动态内存多次释放

int test()
{
	int* p = (int*)malloc(100);
	free(p);
	free(p);//重复释放!
}

动态开辟内存忘记释放(内存泄漏)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值