C语言之动态内存管理_柔性数组篇(2)

目录

柔性数组的特点

柔性数组的使用 

动态内存函数增容柔性数组模拟实现 

柔性数组的优势


今天接着来讲解一下柔性数组知识。

柔性数组的特点

C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做【柔性数组】成员。

  • 结构体中
  • 最后一个成员
  • 未知大小的数组【柔性数组】
struct Stu
{
	char c;
	int i;
	int arr[];
	//也可以这样写int arr[0]
	//未知大小的数组 -柔性数组成员
};
  • 结构中的柔性数组成员前面必须至少一个其他成员。
  • sizeof 返回的这种结构大小不包括柔性数组的内存。
  • 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。 

我们来验证一下 【sizeof 返回的这种结构大小不包括柔性数组的内存。】--->【验证成功】


#include<stdio.h>
struct Stu
{
	char c;//1 
	int i;//4  
	//对齐规则:8
	int arr[];
	//也可以这样写int arr[0]
	//未知大小的数组 -柔性数组成员
};
int main()
{
	printf("%d", sizeof(struct Stu));
	return 0;
}

 

 验证完之后,我们再来学习一下【动态内存函数在柔性数组上的应用】吧! 


#include<stdio.h>
struct Stu
{
	char c;//1 
	int i;//4  
	//对齐规则:8
	int arr[];
	//也可以这样写int arr[0]
	//未知大小的数组 -柔性数组成员
};
int main()
{
	struct Stu* p = (struct Stu*)malloc(sizeof(struct Stu)+20);//arr里放5个整型
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	free(p);
	p = NULL;
	return 0;
}

#include<stdio.h>
struct Stu
{
	char c;//1 
	int i;//4  
	//对齐规则:8
	int arr[];
	//也可以这样写int arr[0]
	//未知大小的数组 -柔性数组成员
};
int main()
{
	struct Stu* p = (struct Stu*)malloc(sizeof(struct Stu)+20);//arr里放5个整型
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	//发10个整型
	struct Stu* s = (struct Stu*)realloc(p, sizeof(struct Stu) + 40);
	if (s != NULL)
	{
		p = s;
	}
	else
	{
		perror("realloc");
		return 1;
	}
	//释放
	free(p);
	p = NULL;
	return 0;
}

 想必大家都知道为什么叫柔性数组,因为【利用realloc任意调整数组的空间大小】记得及时释放

 柔性数组需要对齐吗?动动小手测试一下。需要40 

柔性数组的使用 

对柔性数组赋值1,2,3,4,5并打印出来。

#include<stdio.h>
#include<stdlib.h>
struct Stu
{
	char c;//1 
	int i;//4  
	//对齐规则:8
	int arr[];
	//也可以这样写int arr[0]
	//未知大小的数组 -柔性数组成员
};
int main()
{
	struct Stu* p = (struct Stu*)malloc(sizeof(struct Stu)+20);//arr里放5个整型
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	p->c = 't';
	p->i = 7;
	int i = 0;
	for (i = 0;i < 5; i++)
	{
		p->arr[i] = i+1;
	}
	for (i = 0; i < 5; i++)
	{
		printf("%d ", p->arr[i]);
	}
	//放10个整型
		struct Stu* s = (struct Stu*)realloc(p, sizeof(struct Stu) + 40);
	if (s != NULL)
	{
		p = s;
	}
	else
	{
		perror("realloc");
		return 1;
	}
	//释放
	free(p);
	p = NULL;
	return 0;
}

柔性数组还可以应用于【通讯录 】,后期我们也会去实现通讯录,并用【柔性数组】优化。

动态内存函数增容柔性数组模拟实现 

  • 需要释放两次和开辟两次空间
  • 频繁的不连续开辟,内存碎片很多,内存的利用率很低
#include<stdio.h>
#include<stdlib.h>
struct S
{
	char c;
	int i;
	int* a;
};
int main()
{
	//为结构体开辟空间
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	ps->c = 'T';
	ps->i = 7;
	ps->a = (int*)malloc(20);
	if ( ps->a == NULL)//注意写法ps->a
	{
		perror("malloc");
		return 1;
	}
	//使用
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->a[i] = i + 1;
	}
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->a[i]);
	}
	//不够继续增加容
	int* pd = (int*)realloc(ps->a, 40);
	if (pd != NULL)
	{
		ps->a = pd;
	}
	else
	{
		perror("realloc");
		return 1;
	}
	printf("\n");
	//再次赋值
	int j = 0;
	for (j = 0; j < 10; j++)
	{
		ps->a[j] = j + 1;
	}
	for (j = 0; j < 10; j++)
	{
		printf("%d ", ps->a[j]);
	}
	//释放
	free(ps->a);
	ps->a = NULL;
}

 

柔性数组的优势

 通过上面两端代码【柔性数组】和【指针】的比较,即便它们的功能一致,我们可以清晰的发现【柔性数组的优势】。

【优点1】方便释放 一次性就释放完全


如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。 

【优点2】这样有利于访问的速度,减少内存碎片,提高空间利用率


 连续的内存有益于提高访问速度,也有益于减少内存碎片。

最后,有一篇文章,感谢他让我受益匪浅。 

C语言结构体里的成员数组和指针 | 酷 壳 - CoolShell

【建议书】C陷阱与缺陷  高质量C\C++ 剑指offer 明解C语言等等 

最后我想对我自己说,其实学习就是这样,刚开始并不喜欢计算机这门专业。其实我很想去选小语种西班牙语去到国外做翻译去看世界,而且我的理科思维并不好,但是在选择这门学科之后,当我开始认真的学习一些C语言的语法之后,我看到我自己独立写出来的游戏小程序的时候,还是挺有成就感,特别看到博客被大家看到,传递一些知识,还是很幸福的。写博客挺费时间的,但是我希望小唐可以一直坚持的学习,坚持写博客和交流知识。慢慢走,每一步都算数的。

✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!

代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com

联系------→【邮箱:2784139418@qq.com】

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

唐唐思

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

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

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

打赏作者

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

抵扣说明:

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

余额充值