【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)

Chatgpt-4o:人工智能领域的革新与未来展望

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;领域正经历着前所未有的变革。作为这一领域的佼佼者&#xff0c;OpenAI于2024年5月13日正式发布了其最新旗舰模型——Chatgpt-4o。这一模型不仅在技术上取得了重大突破&#xff0c;更在用户体验、应用场景以及…

【OS】AUTOSAR OS系统调用产生Trap的过程详解

目录 前言 正文 1.Os_Hal_Trap使用示例 2. Os_Hal_Trap的定义 3. syscall详解详解

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;大而全 宏内核系统…

2024蓝桥杯国赛C++研究生组游记+个人题解

Day0 开始复习&#xff0c;过了一遍大部分板子 本来打算再学一遍SAM&#xff0c;但是想到去年考了字符串大题今年应该不会再考了吧。。 过了一遍数据结构和图论&#xff0c;就1点了 两点的时候还没睡着&#xff0c;舍友打游戏好像打到2点过。。 Day1 相当困 第一题&…

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…

Re0:从零开始的C++游戏开发 【下】

Re0:从零开始的C游戏开发 &#xff08;下&#xff09; 这是蒟蒻观看B站upVoidmatrix的课程从零开始的提瓦特幸存者的个人笔记【自用】 前言&#xff1a;采用适用于小白的easyx图形库。 第三集 提瓦特の幸存者&#xff08;下&#xff09; 3.1 用户界面实现和设计模式基础 3…

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

背景 党的十八届四中全会提出全面推进依法治国的总目标和重大任务。全会通过的《中共中央关于全面推进依法治国若干重大问题的决定》&#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…

在浏览器里面输入 url,到浏览器显示页面中间发生了什么?

当用户在浏览器中输入URL&#xff08;例如https://www.example.com&#xff09;按下回车键&#xff0c;到浏览器显示页面&#xff0c;这中间浏览器会执行以下步骤&#xff1a; 浏览器解析URL&#xff1a;浏览器解析URL&#xff0c;提取出协议&#xff08;如HTTP或HTTPS&#xf…

每天一个数据分析题(三百四十二)

根据量化对象是业务行为结果还是财务行为结果&#xff0c;可以将指标分为业务指标及财务指标两大类&#xff0c;以下说法正确的是&#xff1f; A. 财务指标是按照财务规则来对财务情况进行量化的指标 B. 业务指标是按照业务规则来对业务情况进行量化的指标 C. 业务指标需要按…