柔性数组详细讲解

动态内存函数的使用和综合实践-malloc,free,realloc,calloc-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/Jason_from_China/article/details/137075045

柔性数组存在的意义

 柔性数组在编程语言中指的是可以动态调整大小的数组。相比固定大小的数组,它们提供更大的灵活性,主要存在以下意义:


1. **动态调整大小**:

在程序运行过程中,如果需要增加或减少数组的大小,柔性数组可以避免创建新的数组和复制元素到新数组中的开销。


2. **节省内存**:

柔性数组在初始化时不需要指定确切的大小,因此可以在不知道确切需求的情况下启动程序,节省了初始化的时间和内存空间。


3. **提高效率**:

由于不需要预先分配固定大小的内存,柔性数组可以在数组实际需要的大小上分配内存,减少了内存的浪费。


4. **易于扩展**:

当程序需求变化,需要增加存储空间时,柔性数组更容易进行扩展。


5. **减少代码复杂性**:

通过动态内存管理,程序员可以简化代码,不必担心数组大小的问题。


6. **灵活的数据处理**:

在处理数据时,如果数据量不稳定或者在处理过程中数据量发生变化,柔性数组可以更有效地处理这些情况。
在不同的编程语言中,如C++中的`vector`,Java中的动态数组,都是柔性数组的实现。这些数据结构在现代软件开发中非常常见,因为它们提供了一种高效、灵活的方式来处理动态变化的数据集合。

———————————————————————————————————————————

柔性数组建立在结构体里面

而且是最后一个成员(这里一定要记住,是最后一个成员)

数组没有指定大小

这个数组才是柔性数组

至少有一个其他成员 (柔性数组的条件)-->判断条件

——————————————————————————————————————————— 

柔性数组写法1

—————————————————————————————————————————— 

柔性数组写法2

至少有一个其他成员 (柔性数组的条件)

———————————————————————————————————————————

柔性数组的如何在计算机里面计算的 

内存---这里只计算n的空间,不计算柔性数组arr的空间,

不计算 柔性数组的空间,这里通过计算机的计算,我们发现确实是这样

———————————————————————————————————————————

柔性数组开辟空间的使用逻辑(重点)

首先给出一个代码 我们详细解释代码的逻辑

那么柔性数组在这里面是如何使用的呢

1.首先我们进入主函数这里开辟一个空间,空间的大小是一个结构体大小的空间,这里是计算的大小是不包括弹性数组的大小的,计算的是弹性数组之前的大小,因为弹性数组在正式使用之前是没有大小空间这一说的。

malloc(sizeof(struct s));

2.我们开辟完空间之后,如果是按照正常的开辟空间来说,那么此时开辟的空间只需要进行强制类型转化就可以结束了。但是我们这里讲解的是柔性数组,也就是还没有结束。

malloc(sizeof(struct s)+5*sizeof(int));

3.柔性数组的开辟空间,也就是,结构体空间(不包含弹性数组的大小的空间)+你希望的空间大小。因为你的结尾处是有弹性数组的,弹性数组是可以任意变化的。所以后面的加上,加上的是可以变化的空间,也就是弹性数组的空间 ,当然,你要是不加上空间也是可以的。最后进行强制类型转化,并且创建指向这个空间的变量。

struct s*ps=(struct s*)malloc(sizeof(struct s)+5*sizeof(int));

也就是这样用指针进行接收,强制类型转化为结构体,因为是结构体类型的,自然需要用结构体进行接收,结构体进行强制类型转换。

这段代码的图解

这段代码意味着

四个字节给n

20个字节给arr

把这个地址给ps

这里ps指向的是ps这一框空间

这里也可以通过realloc调整空间

柔性数组为什么放到后面:

也就是 结构体的这个大小是柔性变化的

所以需要放到后面 方便空间的柔性

使用

柔性数组

———————————————————————————————————————————

柔性数组延长开辟空间的使用逻辑(重点)

这里神奇的来了 realloc函数可以二次对空间进行扩展。

这里可以进行扩展空间

1,malloc在弹性数组里面的使用(上面讲解复制来的)

1.首先我们进入主函数这里开辟一个空间,空间的大小是一个结构体大小的空间,这里是计算的大小是不包括弹性数组的大小的,计算的是弹性数组之前的大小,因为弹性数组在正式使用之前是没有大小空间这一说的。

malloc(sizeof(struct s));

2.我们开辟完空间之后,如果是按照正常的开辟空间来说,那么此时开辟的空间只需要进行强制类型转化就可以结束了。但是我们这里讲解的是柔性数组,也就是还没有结束。

malloc(sizeof(struct s)+5*sizeof(int));

3.柔性数组的开辟空间,也就是,结构体空间(不包含弹性数组的大小的空间)+你希望的空间大小。因为你的结尾处是有弹性数组的,弹性数组是可以任意变化的。所以后面的加上,加上的是可以变化的空间,也就是弹性数组的空间 ,当然,你要是不加上空间也是可以的。最后进行强制类型转化,并且创建指向这个空间的变量。

struct s*ps=(struct s*)malloc(sizeof(struct s)+5*sizeof(int));

也就是这样用指针进行接收,强制类型转化为结构体,因为是结构体类型的,自然需要用结构体进行接收,结构体进行强制类型转换。

2,realloc在弹性数组里面的使用讲解:

1.首先我们知道realloc函数的使用规则,realloc(目标函数,扩展的空间的大小),同时realloc使用的时候可能会导致开辟空间的失败,所以我们需要先拿指针进行接收,再进行判断和赋值。

2.我们需要知晓弹性数组的使用规则,也就是sizeof计算的是字节的大小是不包含弹性数组的。所以需要加上你需要的实际的空间的大小。也就是,原本20个字节的大小,你扩展40,那么加一起就是60空间的大小。你可以不使用,但是使用的时候,最多可以使用的是60个空间的大小。

3.接下来我们进行代码的解释,malloc的代码逻辑是一样的,所以我们从realloc开始讲解,这里的我们直接使用realloc是可能开辟空间导致失败的,所以我们选择用一个指针指向开辟的空间,只要不是空地址,我们就继续下面的工作。也就是

int *ptr=(struct s*)realloc(ps,sizeof(struct s)+10*sizeof(int));

解释:这里开辟的是ps指向的空间,创建指针变量指向ps指向的空间,防止创建的时候失败,导致销毁。

4.总结使用代码,想要进行赋值,打印出来,最后我给出了代码。

柔性数组第一种的代码总结

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
struct s
{int i;int arr[];
};
//sizeof(struct s):这个表达式计算了 struct s 类型的大小。
// 这包括了 struct s 中所有字段的大小,但不包括动态分配的数组 arr 的大小,
// 因为数组的大小取决于它所包含的元素的数量。
// struct s 中的 int i 字段占用4个字节(在大多数现代平台上是这样),
// 而 int arr[] 是一个未指定大小的数组,所以我们不知道它占用的空间 
// 而后面 我们进行数组的使用的时候 +也就是加上想要延长的数组的长度,
// 所以这也就是为什么柔性数组是需要放到结构体最后的
int main()
{//这里是内存空间的扩展struct s* ps = (struct s*)malloc(sizeof(struct s) + 5 * sizeof(int));if (ps == NULL){perror("struct:");return 1;}for (int i = 0; i < 5; i++){ps->arr[i] = i;}for (int i = 0; i < 5; i++){printf("%d ", ps->arr[i]);}struct  s pf = { .i = 1 };printf("\n%d\n", pf.i);//这里我们认为开辟的空间是5个整形的空间大小 所以我们需要进行这个,对这个弹性数组进行reallocstruct s* ptr = (struct s*)realloc(ps, sizeof(struct s) + 10 * sizeof(int));if (ptr == NULL){perror("realloc:");return 1;}ps = ptr;for (int i = 0; i < 10; i++){ps->arr[i] = i;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}free(ps);return 0;
}

———————————————————————————————————————————

柔性数组扩展空间的第二种实现方案(补充说明)

这里可以放到堆上,也就是先开辟空间,因为柔性数组本身就是弹性的

然后判断是不是空指针,不是继续运行 

进入正题

这里给出五个变量,这里是单独给到柔性数组里面,和版本1不一样。

版本1里面是对整个数组进行内存延伸,这个是连续的

版本2里面是开辟一块一块的内存空间,这个不是连续的

 这样第二种会导致一种情况,

释放的时候需要先释放空间2,再释放1,需要先释放2的空间,不然是找不到2的空间,后释放ps空间。因为正常情况下1,2空间之间还有空间是不被利用的。那么你要是先释放空间1,就会导致找不到后面的空间。

但是第一种就不需要,只需要释放空间1 。

———————————————————————————————————————————

总结

还是第一种方案好

以为malloc使用次数越多

空间碎片越多

空间利用率越小

柔性数组 的优势方案 1 方便内存释放

不像第二种方案 结构体包含指针 需要释放两次

第二个方案 不是连续的空间 所以第一个使用起来方便 方便管理

文章推荐

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

内存的划分 

这里附带两章内存划分图片

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

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

相关文章

STL容器的一些操作(常用的,不全)

目录 string 1.string的一些创建 2.string 的读入和输出&#xff1a; 3.string的一些操作 4.彻底清空string 容器的函数 vector 1.vector的一些创建&#xff1a; 2.vector的一些操作&#xff1a; 3.vector的彻底清空并释放内存&#xff1a; queue 循环队列&#xff1…

兑换码生成算法

兑换码生成算法 兑换码生成算法1.兑换码的需求2.算法分析2.重兑校验算法3.防刷校验算法 3.算法实现 兑换码生成算法 兑换码生成通常涉及在特定场景下为用户提供特定产品或服务的权益或礼品&#xff0c;典型的应用场景包括优惠券、礼品卡、会员权益等。 1.兑换码的需求 要求如…

Pointnet++分类和分割数据集准备和实验复现

5.分类数据集Modelnet40及可视化 Modelnet40分类数据集 原始的modelnet40是off文件&#xff0c;是cad模型 OFF文件是一种用于存储三维对象信息的文件格式&#xff0c;全称为"Object File Format"。它主要用于存储几何体的顶点、边和面信息&#xff0c;以及可能的颜…

面对复杂多变的网络攻击,企业应如何守护网络安全

企业上云&#xff0c;即越来越多的企业把业务和数据&#xff0c;迁移到云端。随着云计算、大数据、物联网、人工智能等技术的发展&#xff0c;用户、应用程序和数据无处不在&#xff0c;企业之间的业务边界逐渐被打破&#xff0c;网络攻击愈演愈烈&#xff0c;手段更为多。 当前…

uni app 扫雷

闲来无聊。做个扫雷玩玩吧&#xff0c;点击打开&#xff0c;长按标记&#xff0c;标记的点击两次或长按取消标记。所有打开结束 <template><view class"page_main"><view class"add_button" style"width: 100vw; margin-bottom: 20r…

Docker容器监控之CAdvisor+InfluxDB+Granfana

介绍&#xff1a;CAdvisor监控收集InfluxDB存储数据Granfana展示图表 目录 1、新建3件套组合的docker-compose.yml 2、查看三个服务容器是否启动 3、浏览cAdvisor收集服务&#xff0c;http://ip:8080/ 4、浏览influxdb存储服务&#xff0c;http://ip:8083/ 5、浏览grafan…

如何利用CSS实现文字滚动效果

1. 使用CSS3的animation属性 CSS3的animation属性可以让元素在一段时间内不停地播放某个动画效果。我们可以利用这个特性来实现文字滚动效果。 我们需要定义一个包含所有需要滚动的文本的容器元素。比如&#xff1a; <div class"scroll-container"><p>…

JAV八股--redis

如何保证Redis和数据库数据一致性 关于异步通知中消息队列和Canal的内容。 redisson实现的分布式锁的主从一致性 明天继续深入看这个系列问题 介绍IO复用模型

【机器学习300问】59、计算图是如何帮助人们理解反向传播的?

在学习神经网络的时候&#xff0c;势必会学到误差反向传播&#xff0c;它对于神经网络的意义极其重大&#xff0c;它是训练多层前馈神经网络的核心算法&#xff0c;也是机器学习和深度学习领域中最为重要的算法之一。要正确理解误差反向传播&#xff0c;不妨借助一个工具——计…

代码随想录算法训练营第24天|理论基础 |77. 组合

理论基础 jia其实在讲解二叉树的时候&#xff0c;就给大家介绍过回溯&#xff0c;这次正式开启回溯算法&#xff0c;大家可以先看视频&#xff0c;对回溯算法有一个整体的了解。 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;带你学透回溯算法&#xff08;理…

深入理解数据结构——堆

前言&#xff1a; 在前面我们已经学习了数据结构的基础操作&#xff1a;顺序表和链表及其相关内容&#xff0c;今天我们来学一点有些难度的知识——数据结构中的二叉树&#xff0c;今天我们先来学习二叉树中堆的知识&#xff0c;这部分内容还是非常有意思的&#xff0c;下面我们…

前端秘法番外篇----学完Web API,前端才能算真正的入门

目录 一.引言 二.元素的获取和事件 1.获取元素 2.各种事件 2.1点击事件 2.2键盘事件 三.获取&修改操作 1.获取修改元素属性 2.修改表单属性 2.1暂停播放键的转换 2.2计数器的实现 2.3全选的实现 3.样式操作 3.1行内样式操作 3.2类名样式操作 四.节点 1.创…

记录Xshell使用ed25519公钥免密链接SSH

试了半天&#xff0c;Xshell好像没办法导入linux生成的ssh公钥,因此需要以下步骤实现免密登录 结论&#xff0c;在linux公钥文件中&#xff0c;将客户端生成的ed25519公钥加上去即可(一个公钥单独一行) 1.使用Linux生成秘钥文件(不需要输入私钥密码passphrase)或者直接创建一…

【Servlet】继承关系以及service方法

文章目录 一、继承关系二、相关方法 一、继承关系 Servlet接口下有一个GenericServlet抽象类。在GenericServlet下有一个子类HttpServlet&#xff0c;它是基于http协议。 继承关系 javax.servlet.Servlet接口​ javax.GenericServlet抽象类​ javax.servlet.http.HttpServ…

生产制造园区数字孪生3D大屏展示提升运营效益

在智慧园区的建设中&#xff0c;3D可视化管理平台成为必不可少的工具&#xff0c;数字孪生公司深圳华锐视点打造的智慧园区3D可视化综合管理平台&#xff0c;致力于将园区的人口、经济、应急服务等各项业务进行3D数字化、网络化处理&#xff0c;从而实现决策支持的优化和管理的…

C++多线程:Atomic原子类与CAS锁详解(十)

1、原子操作的概念 什么是原子操作&#xff1a; 原子被认为是构成物质最小的单位&#xff0c;是不可分割的一个东西。而在程序中原子操作被认为是不可分割的一个步骤或者指令其实我们很简单的程序&#xff0c;在高级语言中被认为是一个步骤的操作&#xff0c;编译成汇编指令之…

Redis从入门到精通(三)Jedis客户端、SpringDataRedis客户端

文章目录 前言第3章 Redis的Java客户端3.1 Jedis客户端3.1.1 快速使用3.1.2 连接池 3.2 SpringDataRedis客户端3.2.1 快速使用3.2.2 自定义序列化3.2.3 StringRedisTemplate 3.3 小结 前言 在上一章【Redis从入门到精通(二)Redis的数据类型和常见命令介绍】中&#xff0c;学习…

Springboot+MybatisPlus+EasyExcel实现文件导入数据

记录一下写Excel文件导入数据所经历的问题。 springboot提供的文件处理MultipartFile有关方法&#xff0c;我没有具体看文档&#xff0c;但目测比较复杂&#xff0c; 遂了解学习了一下别的文件上传方法&#xff0c;本文第1节记录的是springboot原始的导入文件方法写法&#xf…

docker-compse安装es(包括IK分词器扩展)、kibana、libreoffice

Kibana是一个开源的分析与可视化平台&#xff0c;设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。 Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等&#xff0c;直观的展示数据&#xff0c;从而达到高级的数据…

MySQL 优化及故障排查

目录 一、mysql 前置知识点 二、MySQL 单实例常见故障 故障一 故障二 故障三 故障四 故障五 故障六 故障七 故障八 三、MySQL 主从故障排查 故障一 故障二 故障三 四、MySQL 优化 1.硬件方面 &#xff08;1&#xff09;关于 CPU &#xff08;2&#xff09;关…