【C语言】柔性数组

前言

你是否听说过柔性数组呢?如果没有的话,就一起了解一下吧。

(没有malloc free calloc realloc 四个函数的前置知识的朋友最好先阅读一下我的“动态内存管理”一文,因为下面会涉及到。)

介绍

C99中,结构中的最后一个元素允许是位置大小的数组,这就叫“柔性数组”成员。

比如:

struct st_type
{int i;int a[0];//柔性数组成员
};

或者:

struct st_type
{int i;int a[];//柔性数组成员
};

有的编译器支持前一种写法,有的则支持后一种,vs则是两种写法都可以。 

由此,我们可以看出柔性数组的定义。

定义

1.在结构体中

2.最后一个成员

3.未知大小的数组

 注意,柔性数组不是一个独立的数组,而是结构的一个成员。

柔性数组的特点(要求):

1.结构中的柔性数组成员前面必须至少一个成员。

        因为柔性数组的大小是未知的,如果前面没有成员,结构大小没法算。

2.sizeof返回这种结构大小时不包括柔性数组的内存。(请看下面例子

3.包含柔性数组的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

例子:

 

可以看到我们的结构体大小果然只有4bytes(字节),柔性数组的大小确实没有被算在内。

现在,我们再来解释比较重要的第三条特点:

包含柔性数组的结构,用malloc()函数进行内存的动态分配

如果我们现在想创建一个S类型的结构体变量,我们一般不会这么写:

struct S
{int n;int arr[0];
};int main()
{struct S s;return 0;
}

因为当我们这么写,s的大小就为4bytes,我们的arr就没有内存了:

 Plan A

为了能够给arr开辟空间,我们需要这么写:

//给arr开辟20个int型大小
struct S* ps=(struct S*)malloc(sizeof(struct S)+20*sizeof(int));

(头文件stdlib.h别忘了包含)

此时我们的ps能访问s里的n和arr

ps->n=100;
int i=0;
for(i=0;i<20;i++)
{ps->arr[i]=i+1;
}

别忘了检查开辟是否成功:

if(ps==NULL)return 1;

现在我们也能用realloc来调整这块空间,柔性数组可以变大变小。(变长数组可做不到)

假设我们现在将柔性数组大小调整为40个整型大小:

我们只想调整arr的大小,但是我们的动态开辟是从n(也就是S型变量的起始地址开始的),所以我们的调整也得从这里开始

struct S* ptr=(struct S*)realloc(ps,sizeof(struct S)+40*sizeof(int));
//不能用ps直接接收因为可能开辟失败
if(ptr!=NULL)
{ps=ptr;ptr=NULL;//不用ptr,及时置为空指针,以防变为野指针
}
else
{return 1;
}

最后别忘了将ps释放和置为空指针。

Plan B

其实上面这个对包含柔性数组的结构体分配内存的方案还有另一种同样效果的方案B,在这里可以做一种对比:

你可能会想到,既然是柔性数组在变大变小,那何不改为:

struct S
{int n;int *arr;//改写成指针形式
};

然后传arr进行realloc呢?

为了和Plan A达到相同效果,将n也动态内存开辟(让n也开辟在堆区上)

那么我们就这么写:

struct S
{int n;int *arr;//这里如果写成arr[],下面用ps->arr=tmp会提示得是可修改的左值a
};int main()
{//让n的空间也在堆上,所以也用mallocstruct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){perror("malloc");return 1;}return 0;
}

然后我们动态开辟柔性数组部分:

int* tmp = (int*)malloc(20 * sizeof(int));
if (tmp!= NULL)
{ps->arr = tmp;
}
else
{return 1;
}

 然后我们可以对柔性数组扩容

//调整空间
tmp=(int*)realloc(ps->arr, 40 * sizeof(int));
if (tmp != NULL)
{ps->arr = tmp;
}
else//处理调整失败的情况
{perror("realloc");return 1;
}

然后我们就可以使用这块空间。

使用完同样记得释放,这个方案有两个开辟的起始地址,需要释放两次。

free(ps->arr);
//ps->arr = NULL;可以写,也可以不写,因为ps置为NULL,ps->arr也找不到地址了
free(ps);
ps = NULL;

那么,我们可以对比这两种方案。前一种是只malloc了一次,后一种malloc了好几次,那么这会存在什么问题呢?

多次malloc:malloc申请的空间是连续的,但一次malloc和另一次malloc申请的空间之间可能会有缝隙,而这些缝隙最后能否被利用上是不一定的。所以还是减少malloc的次数比较好。

这些就是内存碎片,就像教室里坐着的学生,中间会有缝隙。malloc次数越多内存碎片就越多。

总结

柔性数组就是在结构体的最后有一个数组成员,且这个数组的大小可以调整。这样的结构体在开辟内存时需要动态开辟,才能正常使用柔性数组。

到此,本文就结束了,祝阅读愉快^_^

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/20634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python找出100~999之间的水仙花数字

水仙花数字&#xff1a;个位&#xff0c;十位&#xff0c;百位的立方之和等于这个数本身 例如&#xff1a;153 1^35^33^3 for i in range(100, 1000):bw i // 100sw i % 100 // 10gw i % 10if bw ** 3 sw ** 3 gw ** 3 i:print(i)

LeetCode题练习与总结:路径总和Ⅱ--113

一、题目描述 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], target…

FreeRTOS同步互斥与通信

本章简介&#xff1a; 本章是概述性的内容。可以把多任务系统当做一个团队&#xff0c;里面的每一个任务就相当于团队里的一个人。团队成员之间要协调工作进度(同步)、争用会议室(互斥)、沟通(通信)。多任务系统中所涉及的概念&#xff0c;都可以在现实生活中找到例子。 各类RT…

Java大厂面试题第2季

一、本课程前提要求和说明 面试题1&#xff1a; 面试题2&#xff1a; 面试题3&#xff1a; 面试题4&#xff1a; 面试题5&#xff1a; 高频最多的常见笔试面试题目 ArrayList HashMap 底层是什么东东 JVM/GC 多线程与高并发 java集合类

【科研基础】证明积累

1-Bayesian Estimation (P317) Suppose that x = θ + ν w h e r e ν i s a n N ( 0 , σ ) random variable and θ is the value of a n N ( θ 0 , σ 0 ) random variable θ (Fig. 8-7). Find the bayesian estimate θ o f θ . \begin{align…

大学校园广播“录编播”与IP校园公共广播系统技术方案

一、项目概述 1、校园IP网络广播系统概述 大学校园广播系统是学校整个弱电系统中的子系统&#xff0c;它是每个学校不可缺少的基础设施之一&#xff0c;在传递校园文化、传播校园新闻资讯方面发挥着重要的作用。近几年来&#xff0c;虽然视频技术和网络技术在飞速发展&#xf…

操作系统的体系结构:宏内核和微内核

操作系统的体系结构是一个开放的问题。操作系统在核心态为应用程序提供公共的服务&#xff0c;那么操作系统在核心态应该提供什么服务、怎样提供服务&#xff1f;有关这个问题的回答形成了两种主要的体系结构&#xff1a;宏内核和微内核。 宏内核&#xff1a;大而全 宏内核系统…

word里面没有Acrobat选项

加载项被禁止&#xff0c;选择项里面&#xff0c;没有Acrobat选项 文件-》选项 加载项-》com加载项-》转到 添加Acrobat 出现Acrobat选项

[Qt]关于QListWidget、QScrollArea 为什么在QDesigner上设置了之后界面上仍然不生效的问题

前言 最近做了一些有关QListWidget和QScrollArea的控件&#xff0c;我去&#xff0c;这两个控件是真的坑&#xff0c;明明我在QDesigner的操作界面上对这两个控件的界面进行了修改&#xff0c;但是编译出来的软件就是看上去什么都没有&#xff0c;很坑&#xff0c;Gpt也没解决…

【linux】宝塔,首页挂载磁盘,显示使用情况

挂载前&#xff1a; 挂载后&#xff1a; 数据无价&#xff0c;建议&#xff1a;备份需要挂载的磁盘&#xff0c;或者使用新磁盘来进行操作。 1、下载自动挂载磁盘的脚本&#xff1a; wget -O auto_disk.sh http://download.bt.cn/tools/auto_disk.sh 2、给脚本添加执行权限&a…

省级交通运输行政执法综合管理平台项目实施方案

背景 党的十八届四中全会提出全面推进依法治国的总目标和重大任务。全会通过的《中共中央关于全面推进依法治国若干重大问题的决定》&#xff0c;开启了中国法治建设的新时代&#xff0c;依法治国已经成为党领导人民治理国家的基本方略。 为了贯彻和落实《交通运输信息化“十三…

资深人士称:AI开发游戏会降低游戏成本和体验,不会降低就业率

易采游戏网6月1日最新消息&#xff1a;本周在TD Cowen会议上&#xff0c;R星的母公司Take-Two的CEO Strauss Zelnick对于人工智能(AI)是否会影响游戏开发行业表达了自己的看法。他坚定地认为&#xff0c;AI绝对会改变游戏的制作方式&#xff0c;但不会降低游戏行业的就业水平。…

Maven打包错误:无效的源发行版:17

1. 报错问题 在用maven进行打包时&#xff08;clean & install&#xff09;&#xff0c;报如下错误&#xff1a; 一开始让我很摸不着头脑&#xff0c;我确定我的pom.xml&#xff0c;还有IDEA中的Project Settings是正确的。 2. 排查 尽管确定&#xff0c;但还是一个个排…

秒杀基本功能开发(显示商品列表和商品详情)

文章目录 1.数据库表设计1.商品表2.秒杀商品表3.修改一下秒杀时间为今天到明天 2.pojo和vo编写1.com/sxs/seckill/pojo/Goods.java2.com/sxs/seckill/pojo/SeckillGoods.java3.com/sxs/seckill/vo/GoodsVo.java 3.Mapper编写1.GoodsMapper.java2.GoodsMapper.xml3.分别编写Seck…

VS(visual studio)搭建QT开发环境插件安装

优先安装QT Qt6 官网QtCreator 下载与安装方法win10_qt6下载-CSDN博客 如果安装vs2019,打开installer,安装c环境 选择c 下载vsix后&#xff0c;双击安装即可。 插件下载&#xff1a; Index of /qtproject/official_releases/vsaddin/ 创建QT项目&#xff1a; 创建完成&…

4K高刷显示器 - 蚂蚁电竞ANT27VU

可以毫不夸张地说&#xff0c;每一局游戏最终能够取得胜利&#xff0c;实际上都与一套极为优秀的电竞 PC 有着紧密的关联&#xff0c;因为其能够提供强大的性能支持与流畅的体验。同样的道理&#xff0c;一套优秀的电竞 PC 若想发挥出最佳的效果&#xff0c;那也都离不开一台能…

【Java】面向对象的三大特征:封装、继承、多态

封装 什么叫封装&#xff1f; 在我们写代码的时候经常会涉及两种角色&#xff1a; 类的实现者 和 类的调用者。 封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的&#xff0c; 只要知道如何使用类就行了&#xff0c;这样就降低了类使用者的学习和使用成本&a…

游戏主播到底是为游戏宣传还是蹭游戏带来的热度

易采游戏网6月1日最新消息&#xff1a;近日知名游戏主播周淑怡在社交平台上发表了自己对《地下城与勇士》手游(简称DNF手游)的点评。作为一款拥有庞大粉丝基础的端游改编作品&#xff0c;DNF手游自发布以来便受到了广泛关注。而周淑怡的点评不仅聚焦于游戏体验本身&#xff0c;…

Python代码:二十七、append函数

1、题目 牛牛有一个name [Niumei, YOLO, Niu Ke Le, Mona] 记录了他最好的朋友们的名字&#xff0c;请创建一个二维列表friends&#xff0c;使用append函数将name添加到friends的第一行。 假如Niumei最喜欢吃pizza&#xff0c;最喜欢数字3&#xff0c;YOLO最喜欢吃fish&…

Linux实验报告(一)——Linux系统安装与简单配置

目录 一、实验名称&#xff1a; 二、仪器、设备&#xff1a; 三、参考资料&#xff1a; 四、实验目的&#xff1a; 五、实验内容&#xff08;步骤&#xff09;&#xff1a; 六、实验数据&#xff08;程序&#xff09;记录&#xff1a; 七、实验结果分析&#xff1a; 八、…