C语言学习总结(九)------动态内存管理与柔性数组

什么是动态内存

动态内存是指在程序运行期间,由程序员申请内存及释放的内存。

为什么需要动态内存分配

1.静态开辟内存不够灵活。
2.栈空间有限(小)。
3.某些条件下难以满足程序员的要求。例如需要一个在程序运行期间才知道大小的数组。

如何动态分配内存

C语言提供了四个关于内存分配的函数。malloc calloc realloc free,需要的头文件都在<stdlib.h>中。
malloc与callocc

void *malloc( size_t size );
void *calloc( size_t num, size_t size );

相同点: 两个函数都是在堆上动态的开辟一块连续的存储空间,开辟成功返回这块空间的首地址,开辟失败则 返回NULL,因此我们可以利用返回值来进行判断内存是否开辟成功,也必须进行判空操作!
因为函数的返回类型是void*因此该函数与类型无关,只是以字节为单位动态的开辟一块空间,至于怎样用,就是程序员的事了,只需进行一次强制类型转换,转换成想用的类型就行。申请的内存必须手动释放掉,否则会造成内存泄漏。
不同点: malloc开辟的空间里面的数据是随机值,并没有初始化。calloc会把开辟的每个字节初始化为0.
用法举例

int main()
{
	int* p = (int*)malloc(10 * sizeof(int));//动态开辟40个字节的内存
	if (NULL == p)  //判空
	{
		printf("Error");
		exit(1);
	}
	else
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			*(p + i) = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", *(p + i));
		}
		printf("\n");
	}
	free(p);   //释放内存
	system("pause");
	return 0;
}

在这里插入图片描述

ralloc

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

realloc函数可以调整我们动态申请的内存,使得动态内存管理更加灵活。
两个参数 memblock:需要调整的内存的首地址,size为调整之后的大小。
用法举例

int main()
{
	int* p = (int*)malloc(10 , sizeof(int));//动态开辟40个字节的内存
	int* q = NULL;
	if (NULL == p)  //判空
	{
		printf("p: Error");
		exit(1);
	}
	*q = realloc(p, 100 * sizeof(int));//此处不再需要强制类型转换。由原来的40个扩大至400个
	if (NULL == q)  //判空
	{
		printf("q: Error");
		exit(1);
	}
	else
	{
		p = q;
	}	
	free(p);   //释放内存
	p = NULL;  //置空
	system("pause");
	return 0;
}

free

void free( void *memblock );

对动态开辟的内存进行释放,其中memblok,只能是指向动态内存空间的地址。而且memblock的值可以为空。free掉内存后只是取消了指针和内存之间的映射关系,指针仍然指向那块存储空间,存储空间的数据仍在,但通过该指针不能再访问这块内存了!
为什么利用malloc申请的内存是动态的?
1.mallloc是一个函数,函数在调用的时候才会执行,因此malloc申请的内存是在程序运行期间申请的。而静态内存是在编译期间分配的。
2.malloc申请的内存是可变的。

注:动态内存分配只能整体分配,整体释放

int main()
{
	int* p = (int*)malloc(10*sizeof(int));
	if (p!=NULL)
	{
		p++;//p已经不再是指向起始位置了!
	}
	free(p);
	system("pause");
	return 0;
}

在这里插入图片描述
程序已经崩溃了。

柔性数组

概念:柔性数组是指在一个结构体中,最后一个元素是一个长度为0的数组。
目的:结构体内包含柔性数组是为了在结构体内创建一个变长数组。
例如:

struct Stu
{
	int a;
	int arr[0];
};
//--------------------------
struct Stu
{
	int a;
	int arr[];
};

柔性数组的特点:
1.柔性数组前必须至少有一个元素。
2.sizeof返回值测得大小不包括柔性数组。
3.可以利用动态内存分配的方式为柔性数组开辟空间。

柔性数组大概是这样的:
在这里插入图片描述
黑色框内是a的空间,红色框内是数组arr的空间。但用sizeof测得结构体的空间只是黑色框的部分。

柔性数组的使用

struct Stu
{
	int a;
	int arr[];
};
int main()
{
	struct Stu *st = (struct Stu*)malloc(sizeof(struct Stu) + 10 * sizeof(int));
	if (st != NULL)
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			st->arr[i] = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", st->arr[i]);
		}
		printf("\n");
		free(st);
	}
	system("pause");
	return 0;

利用柔性数组的优点:其实可以在结构体内定义一个指针,然后利用指针指向堆上的一块内存,但这样做就必须单独对这块内存进行管理。而利用柔性数组呢,可以通过结构体指针一次性管理整个内存,一次申请一次释放,因此柔性数组的优点是内存方便管理,提高效率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中,动态数组柔性数组(flexible arrays)是两种处理数组大小的不同方法。 动态数组(也称为动态内存分配)通常是在程序运行时根据需要动态地分配和释放内存空间的数组。程序员需要使用`malloc()`或`calloc()`等函数来分配内存,并使用`free()`来释放内存。动态数组的大小在编译时并不固定,可以根据需要改变。由于数组大小的灵活性,它们更适用于需要频繁调整大小的情况,但对内存管理的要求较高。 柔性数组(在C99标准后引入)是数组的一种特殊形式,它允许数组名后面跟一个可选的省略的整数,这个整数表示数组的有效元素数量,但不是数组的实际大小。例如,`int arr[10]; int arr[];`中,`arr[]`就是一种柔性数组,编译器会自动为它预留一定数量的内存,直到遇到第一个非数组元素。柔性数组的最大好处是代码简洁,不需要显式指定大小,但它们的大小仍然受限于栈的大小,不能像动态数组那样任意增长,且不能跨多个函数调用。 相同点: - 都允许数组的大小在一定程度上具有灵活性。 - 可以在声明时不明确指定数组的大小。 不同点: - 动态数组:内存分配在运行时完成,可以在程序执行过程中创建和销毁。大小可动态调整,需要手动管理内存。 - 柔性数组数组大小在编译时确定,但可以通过数组名称后的省略整数部分灵活指定有效元素的数量,不能动态扩展,且受限于栈空间。 - 内存管理动态数组需要程序员手动分配和释放内存,柔性数组由编译器自动管理,无需显式释放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值