【C语言】动态内存管理(malloc、calloc、realloc,柔性数组)

本文介绍了C语言动态内存管理,包括malloc、calloc、realloc函数的使用及内存泄漏的危害。详细阐述了动态内存管理函数的常见错误和注意事项,并探讨了柔性数组的特点和优势,强调了连续内存分配对访问速度和内存管理的积极影响。

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

一. C语言动态内存管理库函数介绍

1.1 为什么存在动态内存管理

我们已经掌握的内存开辟方式有:

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {
   0};//在栈空间上开辟10个字节的连续空间

但是上述的开辟空间的方式有两个特点:

  1. 空间开辟大小是固定的。

  2. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。也就是说当我们在定义变量时并不知道会使用多少的内存,这时候就需要进行动态内存开辟!
上述两种开辟内存方法一个在栈上开辟,一个在堆上开辟。
在C语言<stdlib.h><malloc.h>内置的库中有能够进行动态内存开辟的库函数。

1.2 动态内存管理函数

🎉malloc

//Allocates memory blocks.
void *malloc( size_t size );

参数size_t size表示需要开辟的内存的字节数。该函数会返回开辟好内存的首地址,如果开辟失败返回NULL

比如使用malloc函数开辟拥有10个整型元素的数组,那需要开辟的字节数为40字节。

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

int main()
{
   
	//使用malloc开辟一个含10个的整型元素数组
	int* arr = NULL;
	int* p = (int*)malloc(sizeof(int) * 10);//为数组开辟内存
	if (p == NULL)
	{
   
		printf("内存申请失败!\n");
		exit(-1);//内存申请失败,程序没有再进行的必要,直接强制结束程序
	}
	arr = p;//确认内存开辟成功再将此内存交给数组
	p = NULL;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
   
		arr[i] = i + 1;
		printf("%d ", arr[i]);
	}
	return 0;
}

因为malloc函数的返回值类型为void*,所以需要将已经开辟好的内存的首地址强制转换成整型指针类型。

运行结果:

1 2 3 4 5 6 7 8 9 10
C:\Users\HP\Desktop\gitee\test\world\test\x64\Debug\test.exe (进程 13104)已退出,代码为 0。
按任意键关闭此窗口. . .

🎉free

对于动态内存开辟的空间,开辟的地址是在堆上的,使用完了是需要返还给操作系统的,C语言中专门有一个回收动态开辟内存的函数——free。当然,程序结束时,会自动释放内存。

//Deallocates or frees a memory block.
void free( void *memblock );

参数void *memblock表示动态开辟内存的首地址,注意这个地址只能是动态开辟内存的首地址,其他的地址都不行!如果传入的地址为NULL,则这个函数什么都不会做。

在上面所举例创建10个整型数组的程序中,就忽略了动态内存的释放,存在内存泄漏的风险。所以正确完整的程序应该为:

参数void *memblock表示动态开辟内存的首地址,注意这个地址只能是动态开辟内存的首地址,其他的地址都不行!如果传入的地址为NULL,则这个函数什么都不会做。
在上面所举例创建10个整型数组的程序中,就忽略了动态内存的释放,存在内存泄漏的风险。所以正确完整的程序应该为:

int main()
{
   
	//使用malloc开辟一个含10个的整型元素数组
	int* arr = NULL;
	int* p = (int*)malloc(sizeof(int) * 10);//为数组开辟内存
	if (p == NULL)
	{
   
		printf("内存申请失败!\n");
		exit(-1);//内存申请失败,程序没有再进行的必要,直接强制结束程序
	}
	arr = p;//确认内存开辟成功再将此内存交给数组
	p = NULL;
	int i = 0;
	for (i = 0; i < 10; i++)
	{
   
		arr[i] = i + 1;
		printf("%d ", arr[i]);
	}
	free(arr);//有借有还,再借不难
	arr = NULL;//好习惯:内存释放后,将指针变量置空
	return 0;
}

运行结果:

1 2 3 4 5 6 7 8 9 10
C:\Users\HP\Desktop\gitee\test\world\test\x64\Debug\test.exe (进程 13104)已退出,代码为 0。
按任意键关闭此窗口. . .

🎉内存泄漏的危害:

如果动态内存已经使用完了,但不还给操作系统,也就是没有释放内存,就有可能造成内存泄漏的风险。对于其危害,举个栗子,如果在服务器上存在内存泄漏,则可能造成服务器崩溃。因为服务器是一直工作的,一旦存在内存泄漏,使用完的内存不还回去,久而久之,服务器内存被占用的越来越多,终有一天由于内存不足而造成服务器崩溃。

🎉calloc

该函数功能与malloc非常相似,仅仅多了个初始化的功能,就是说在动态内存开辟时,自动将内存中的元素初始化为0。

//Allocates an array in memory with elements initialized to 0.
void *calloc( size_t num, size_t size );

参数size_t num表示元素个数,size_t size表示每个元素所占字节数大小。

int main()
{
   
	//使用malloc开辟一个含10个的整型元素数组
	int* arr 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morning_Yang丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值