动态内存管理

动态内存管理是程序在运行时根据需要动态分配内存的方法。malloc用于分配指定字节数的内存,calloc除了分配内存外还会初始化为0。realloc可以调整已分配内存的大小,当空间不足时可能会移动数据。free用于释放不再使用的内存,防止内存泄漏。在使用这些函数时,需要注意指针的正确使用和内存的释放,避免野指针和内存泄漏问题。
摘要由CSDN通过智能技术生成

一 简要介绍

*在引入动态内存管理之前,相信不少人有这样的困惑:什么是动态内存管理?

简而言之,动态内存管理就是在内存中灵活的开辟空间,只不过这一个空间在内存中所占的大小是不确定的,可变的,既然是变化的,就叫动态内存了。

*简单地了解了一下动态内存管理是什么之后,不少人又有这样的疑问了:

明明在内存中直接开辟各种数据类型也可以,那么动态内存有什么存在的必要?

其实在实际使用的过程中,我们并不是很清楚我们需要多大一块内存,这时候就需要进行动态内存管理了。

*那么我们如何进行动态内存管理呢?

其实malloc,calloc,realloc,free就是专门为解决这一问题而涉及的函数。

这一函数在堆区进行操作。

我们来拓展一下内存区域中数据的存储。

进行动态内存管理实际上就是在堆区上进行的一个操作。

二 动态内存管理操作有关的函数

1开辟空间

malloc

向内存申请一块连续可用的空间,如果开辟成功那么返回指向这一片空间的指针,如果开辟失败,那么返回NULL

①函数的声明与定义:

void*malloc(size_t size)

传入的参数表示你要为这一块内存申请多大的字节。这个空间不可能无限大,它的范围是:0~4294967295

void*则指向开辟的空间。我们需要根据实际意义对他进行强制类型转换。

注意:由于malloc有可能开辟内存空间失败,因此我们使用他的时候要检查他的返回值。

malloc(0)是一种标准未定义的写法,取决于编译器

②接下来演示一下malloc的用法:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdlib.h>
#include<stdio.h>
int main()
{
	
	int* p = NULL;
	p = (int*)malloc(10 * sizeof(int));//包含头文件#include<stdlib.h>,假设在开辟10个char 空间
	int i = 0;

	if (p != NULL)
	{
		for (i = 0; i < 10; i++)
		{
			*(p + i) = 1;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
		return 0;
	}

	
}

类似于开辟了一个可以存储10个int的整型数组。

2 calloc

calloc的功能类似于malloc,只不过传参和初始化不同。calloc会在开辟空间的同时初始化这块空间0。

① 对于calloc的声名和定义

void* calloc (size_t num, size_t size);

num为传入参数的个数,size是每个元素的大小。

举个例子:

 3 动态内存释放 free

其实在动态内存空间开辟完成之后,需要free进行内存的释放,否则就会造成内存泄漏。

注意:

①free只用于动态内存开辟后内存的释放

②需要注意部分内存释放的问题。比如上述的程序,如果循环内是p++的话,那么指针进入循环中就会被更改,指向后面,此时再进行释放的话就会出现此类问题。也可以对指针进行拷贝,那么即使对指针进行了操作。也可以找到首地址。

③指针内存释放之后需要被置成NULL。(避免野指针)

④如果是free(0)则什么事情都不做。也不会出现报错。

因此,对上述的程序进行修改:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdlib.h>
#include<stdio.h>
int main()
{
	
	int* p = NULL;
	p = (int*)calloc(10,sizeof(int));//包含头文件#include<stdlib.h>,假设在开辟10个char 空间
	int i = 0;

	if (p != NULL)
	{
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}
	free(p);
	p = NULL;
		return 0;
}

4 调整开辟的内存——realloc

realloc的功能就是为调整原先开辟的内存空间的大小。

①函数的声明和定义

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

对于ptr,需要调整内存大小的指针的位置。

对于size,调整之后的大小(单位:byte)

对于返回值:

情况一:如果这块空间后面存在一块连续的空间并且这一块空间足够大,那么realloc扩容操作可以直接在这一块空间后面开辟空间。

情况二:如果这块空间后面没有足够的空间了,那么就会在内存的其他位置再找空间,足够放得下再开辟后的总数据。并且将原来的数据销毁。

如图:

 

对于内存开辟失败的话,就会返回空指针,会将原来的数据弄丢。因此需要再引入一个指针,对原先的数据进行维护。举个例子:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdlib.h>
#include<stdio.h>
int main()
{
	
	int* p = NULL;
	p = (int*)malloc(10*sizeof(int));//包含头文件#include<stdlib.h>,假设在开辟10个char 空间
	int i = 0;
	if (p != NULL)
	{
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
	}//malloc之后觉得空间太小了

	int* ptr = NULL;
	ptr =(int*)realloc(p, 15 * sizeof(int));//将调整后的大小用另外的ptr指针操作

	if (ptr != NULL)
	{
		;//业务处理
	}

	free(ptr);
	ptr = NULL;
		return 0;
}

 三 柔性数组

1 什么是柔性数组?

柔性数组是结构体中未指定大小的一个数组,它位于结构体中最后一个成员位置。

注意

计算结构体成员大小的时候,不包含柔性数组的大小

2 生命和定义

struct ALL_STUDENT {
	char school;
	int age;
	char course[];//char course[0]
};

3 使用

可以直接对包含柔性数组的结构体一次性开辟空间,也可以分开开辟。

举例子:

#include<stdio.h>
#include<stdlib.h>
 struct ALL_STUDENT {
	char school;
	int age;
	int course[0];//char course[0]
};

int main()
{
	
	struct ALL_STUDENT* p = (struct ALL_STUDENT*)malloc(sizeof(struct ALL_STUDENT) + 100 * sizeof(int));//为柔性数组开辟100个char的空间
	if (p != NULL)
	{
		for (int i = 0; i < 100; i++)
		{
			p->course[i] = i;
		}

		for (int i = 0; i < 100; i++)
		{
			printf("%d ", p->course[i]);
		}
	}

	free(p);
	p = NULL;

	return 0;
}

一次性开辟的好处是防止忘记多次free指针,并且运行的速度更快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值