十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
目录
网站建设哪家好,找创新互联!专注于网页设计、网站建设、微信开发、成都小程序开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了突泉免费建站欢迎大家使用!🍊前言🍊:
🥝正文:柔性数组🥝:
1.柔性数组的特点:
2.柔性数组的使用:
3.柔性数组的优势:
🍒总结🍒:
🍊前言🍊:🛰️博客主页:✈️銮同学的干货分享基地
🛰️欢迎关注:👍点赞🙌收藏✍️留言
🛰️系列专栏:💐【进阶】C语言学习
🛰️代码仓库:🎉VS2022_C语言仓库
家人们更新不易,你们的👍点赞👍和👉关注👈真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!
关注我,关注我,关注我,你们将会看到更多的优质内容!!
🏡🏡本文重点🏡🏡:
🚅柔性数组特点🚃柔性数组使用🚃柔性数组优势🚏🚏
在上一篇文章中,我们通过几个函数的使用,实现了对动态内存空间的创建、修改和释放,使我们的内存空间成功的“ 动态 ”了起来,而今天我们将通过柔性数组的介绍和使用,真正让我们的动态内存空间得以应用。
🥝正文:柔性数组🥝:或许很多人,甚至包括一些已经参加工作了的老程序员,都未曾听过柔性数组(flexible array)这个概念,但是它又是确实存在的,并且它的存在对于我们进行动态内存管理有着巨大的作用。在 C99 标准中,结构中的最后一个元素的大小允许是位置大小的数组,而我们就将这个未知大小的数组称为柔性数组,并将这个数组成员称为柔性数组成员:
typedef struct A
{
int a;
int arr1[0];
//柔性数组成员
}A;
typedef struct B
{
int b;
int arr2[];
//柔性数组成员
}B;
1.柔性数组的特点:根据上面我们说到的柔性数组定义,我们可以得知,柔性数组主要有以下 3 个特点:
①. 结构中的柔性数组成员前面必须至少存在一个其他成员。
②. sizeof 返回的这种结构大小不包括柔性数组的内存。
③. 包含柔性数组成员的结构用 malloc () 函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
定义中我们可以得知,柔性数组只能作为结构的最后一个元素,并且柔性数组的大小是不确定的,因此在结构中,柔性数组之前至少要有一个其它成员的存在。
因为柔性数组的大小是未知的,因此在计算结构大小时,将不会计入柔性数组的大小:
typedef struct test
{
int i;
int arr[];
}test;
int main()
{
test a;
printf("The size of a is :%d\n", sizeof(a));
return 0;
}
例如上述代码的编译运行结果显示,类型 a 的大小为 4 个字节,即只包含成员整形变量 i:
因为柔性数组的大小是未知的,因此其大小是动态、可变的,故在给其分配空间时,应当使用 malloc 函数进行动态内存分配。同时因为计算结构大小时没有计入柔性数组的大小,因此分配的内存大小应当大于结构的大小,才能容纳下柔性数组的预期大小:
typedef struct test
{
int i;
int arr[];
}test;
int main()
{
test a;
//定义test类型结构体a
test* p = (test*)malloc(sizeof(test) + 40);
//结构的大小为sizeof(test)的大小,故开辟的动态内存大小应当大于该值
free(p);
p = NULL;
return 0;
}
2.柔性数组的使用:有了上节课动态内存管理函数的学习,再来研究柔性数组的使用就十分简单了,我们直接来看示例:
typedef struct test
{
int i;
int arr[];
}test;
int main()
{
test a;
//定义test类型结构体a
test* p = (test*)malloc(sizeof(test) + 40);
//malloc函数的返回值为指针类型,故使用结构体指针test*
//使用malloc函数动态分配空间:test类型结构体的大小(不包含柔性数组) + 40字节
if (p == NULL)
{
perror("malloc");
//判断动态内存空间是否开辟成功
return 1;
}
//业务处理1:
p->i = 10;
int i = 0;
//给柔性数组元素赋值:
for (i = 0; i< p->i; i++)
{
p->arr[i] = i;
}
//打印柔性数组元素:
for(i=0;ii;i++)
{
printf("%d ", p->arr[i]);
}
printf("\n");
test* pp = (test*)realloc(p, sizeof(test) + 80);
//使用realloc函数将结构指针指向的结构a进行扩容
if (pp == NULL)
{
perror("realloc");
//判断动态内存空间是否扩容成功
return 1;
}
//业务处理2:
pp->i = 20;
for (i = 0; i< pp->i; i++)
{
pp->arr[i] = i + 9;
}
for (i = 0; i< pp->i; i++)
{
printf("%d ", pp->arr[i]);
}
printf("\n");
free(pp);
pp = NULL;
return 0;
}
在这个示例中,我们首先定义了 test 类型结构体 a,接着使用了 malloc 函数为结构体 a 与柔性数组分配了动态存储空间;接着在判断非空(动态内存空间分配成功)后给结构体成员 i 与柔性数组 arr 内元素赋值,并进行了打印;再接下来,我们通过使用 realloc 函数将包含柔性数组 arr 的结构体 a 扩容,并在扩容后给结构体内各成员重新赋值并打印;最后释放使用完毕的动态内存空间并将指针置空:
3.柔性数组的优势:但是同时我们又发现,我们使用柔性数组的目的在于希望使结构成员的空间变为动态,可大可小,那么为什么我们不将其写成指针,由指针成员来指向其它的空间呢?如下:
typedef struct test
{
int i;
int* p;
}test;
int main()
{
test* ptr = (test*)malloc(sizeof(test));
if (ptr == NULL)
{
perror("malloc");
return 1;
}
ptr->p = (int*)malloc(40);
if (ptr->p == NULL)
{
free(ptr);
ptr = NULL;
return 1;
}
return 0;
}
我们说,这两种方法都可以达到我们的要求,实现我们的目的,完成同样的功能。但是使用柔性数组有两个显著的好处:
★ 方便内存释放。
★ 有利于提升访问速度。
★ 有利于减少内存碎片。
使用柔性数组的第一个好处是方便于内存释放。我们可以想象一下,假如是在我们的程序之中,用户在完成结构体调用后,可以调用 free 函数将结构体空间进行释放,那么这个时候,下面这种方法进行了二次空间分配,即使用指针指向了另一块动态内存空间,我们不能依赖于用户去发现还有另外一块动态内存空间需要及时进行释放,一旦用户没有注意,就有可能会造成内存释放不及时,严重时甚至有可能会导致内存泄漏问题的产生。反观使用柔性数组,只需调用一次 free 函数即可完成内存空间的释放。
使用柔性数组的第二个优势在于,可以在一定程度上提升我们的内存访问速度。上面这种方式在进行内存访问时,由于使用了二次空间分配,则在访问时的寻址过程中就需要花费更多的时间,而如果我们使用了柔性数组,由于开辟的空间是连续的,在寻址时便可以节省一定的时间。
最后一个优点是,有利于减少内存碎片。这个很好理解,使用二次内存分配的方式所申请到的空间是不连续的,就会在内存中产生更多的空隙,就会导致内存空间中产生更多的内存碎片,而使用柔性数组所申请的空间是连续的,则作为一个个整体,就可以减少内存碎片的产生了。
🍒总结🍒:加上今天内容的学习,我们就可以将动态内存空间灵活的运用在我们的程序代码之中了。并且通过使用并管理动态内存空间,还可以提高我们代码及程序的灵活性和执行效率,有助于我们写出更加优秀的程序。所以,掌握好动态内存的管理与柔性数组的使用,对于我们的工作中的许多项目都大有裨益,希望各位小伙伴们下去以后能够多加练习,切实掌握动态内存管理与柔性数组的相关知识。
🔥🔥有的路,你必须一个人走,这是选择而非孤独🔥🔥
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧