柔性数组(结构体成员)

目录

前言: 

柔性数组:

给柔性数组分配空间: 

调整柔性数组大小:

柔性数组的好处: 


前言: 

       柔性数组?可能你从未听说,但是确实有这个概念。听名字,好像就是柔软的数组,是不是意味着这个数组大小是可以变化的?但是不是只有C99才有可变数组吗?别急,往下看(注:此章节涉及动态内存知识,详情请看:动态内存函数-CSDN博客)。

柔性数组:

       柔性数组是在结构体中使用的,就是说可以不指定数组元素内容,但前面必须至少有一个明确大小的数据类型,且柔性数组必须位于结构体中最后一个成员。

       我们分析上面的话可以得到以下四点重要信息:

  1. 必须在结构体中使用。
  2. 柔性数组必须位于结构体中最后一个成员。
  3. 可以不指定其大小。
  4. 前面必须有一个明确大小的数据类型。
//柔性数组
struct S
{int n;int arr[];//未知大小
};
int main()
{struct S s;printf("%d\n", sizeof(s));//在计算结构体大小时,不包含柔性数组成员return 0;
}

       因为柔性数组没有定义大小,而且柔性数组必须位于结构体的最后一个成员,所以在计算内存的时候,默认把柔性数组的大小计为0。既然没有计算柔性数组的大小,那么到底该如何使用呢?

给柔性数组分配空间: 

       此时就需要用到动态内存函数了,因为结构体大小固定,所以我们想使用柔性数组,就必须给结构体分配空间,所以,结构体的空间也需要动态内存函数来开辟(以至于我们要使用结构体指针)

//柔性数组
struct S
{int n;int arr[];//未知大小
};
int main()
{struct S s;struct S* p =(struct S*) malloc(sizeof(struct S) + 5 * sizeof(int));//开辟原来结构体大小,之后再给柔性数组分配空间为5个int类型p->n = 100;//柔性数组
struct S
{int n;int arr[];//未知大小
};
int main()
{struct S s;struct S* p = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));//开辟原来结构体大小,之后再给柔性数组分配空间为5个int类型p->n = 100;int i = 0;for (i = 0; i < 5; i++){p->arr[i] = i;}//打印printf("%d\n", p->n);for (i = 0; i < 5; i++){printf("%d ", p->arr[i]);}//释放free(p);p = NULL;return 0;
}int i = 0;for (i = 0; i < 5; i++){p->arr[i] = i;}//释放free(p);p = NULL;return 0;
}

       堆区中开辟一块动态内存,并使用p来指向这块动态内存。这块动态内存的大小必须大于结构体大小,柔性数组必须配合动态内存函数使用,因为柔性数组没有办法直接赋值,我们只能配合动态内存函数来对柔性数组赋值。 

       一定注意,我们申请的内存空间也包括了结构体中的首个元素。 

调整柔性数组大小:

       使用realloc函数调整其大小。

//柔性数组
struct S
{int n;int arr[];//未知大小//int arr[0];//也可以这样定义
};
int main()
{struct S s;struct S* p =(struct S*) malloc(sizeof(struct S) + 5 * sizeof(int));p->n = 100;int i = 0;for (i = 0; i < 5; i++){p->arr[i] = i;}struct S*ptr=(struct S*)realloc(p, 44);//将总体大小调整为44字节//相当于给柔性数组扩容为40字节    if (ptr != NULL){p = ptr;}for (i = 0; i < 10; i++){p->arr[i] = i;}for (i = 0; i < 10; i++){printf("%d ", p->arr[i]);}//释放空间free(p);p = NULL;return 0;
}

柔性数组的好处: 

       既然指针指向的空间需要用动态内存函数开辟,那么直接将柔性数组替换为指针不就好了吗?干嘛多此一举,这么费事?此时我就举一个不用柔性数组的例子:

struct S
{int n;int* arr;
};
int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));ps->arr = malloc(5 * sizeof(int));int i = 0;for (i = 0; i < 5; i++){ps->arr[i] = i;}for (i = 0; i < 5; i++){printf("%d ",ps->arr[i]);}//调整大小int* ptr = realloc(ps->arr, 10 * sizeof(int));if (ptr != NULL){ps->arr = ptr;}for (i = 5; i < 10; i++){ps->arr[i] = i;}for (i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}free(ps->arr);ps->arr=NULL;free(ps);ps = NULL;return 0;
}

        有人说,为啥要定义结构体指针呢?以至于还要给结构体开辟空间。大家有没有想过,我们平时使用函数难免会传参,我们知道形参是实参的一份临时拷贝,所以为了节省空间,我们一般是传址调用所以这里使用了结构体指针开辟内存。

       之后来看使用柔性数组完成以上相同功能:

struct S
{int n;int arr[];
};
int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));int i = 0;for (i = 0; i < 5; i++){ps->arr[i] = i;}for (i = 0; i < 5; i++){printf("%d ", ps->arr[i]);}printf("\n");//调整大小int* ptr = realloc(ps, 11 * sizeof(int));if (ptr != NULL){ps = ptr;}for (i = 5; i < 10; i++){ps->arr[i] = i;}for (i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}free(ps);ps = NULL;return 0;
}

       此时我们就会发现,不使用柔性数组需要释放两次由动态内存函数开辟的空间(因为还要释放结构体成员指针开辟的空间),会显得有些繁琐;而柔性数组就不需要释放两次,只需要一次即可满足需求。这就是柔性数组的好处。

       有利于访问速度的提升:因为动态内存开辟是连续的,所以就提高了访问速度,也有利于减少内存碎片。

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

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

相关文章

Web前端 ---- 【Vue】vue路由守卫(全局前置路由守卫、全局后置路由守卫、局部路由path守卫、局部路由component守卫)

目录 前言 全局前置路由守卫 全局后置路由守卫 局部路由守卫之path守卫 局部路由守卫之component守卫 前言 本文介绍Vue2最后的知识点&#xff0c;关于vue的路由守卫。也就是鉴权&#xff0c;不是所有的组件任何人都可以访问到的&#xff0c;需要权限&#xff0c;而根据权限…

深度学习中的池化

1 深度学习池化概述 1.1 什么是池化 池化层是卷积神经网络中常用的一个组件&#xff0c;池化层经常用在卷积层后边&#xff0c;通过池化来降低卷积层输出的特征向量&#xff0c;避免出现过拟合的情况。池化的基本思想就是对不同位置的特征进行聚合统计。池化层主要是模仿人的…

C# 使用Socket进行简单的通讯

目录 写在前面 代码实现 服务端部分 客户端部分 运行示例 总结 写在前面 在.Net的 System.Net.Sockets 命名空间中包含托管的跨平台套接字网络实现。 System.Net 命名空间中的所有其他网络访问类均建立在套接字的此实现之上。 其中的Socket 类是基于与 Linux、macOS 或 W…

SpringBoot 3 集成Hive 3

前提条件: 运行环境&#xff1a;Hadoop 3.* Hive 3.* MySQL 8 &#xff0c;如果还未安装相关环境&#xff0c;请参考&#xff1a;Hive 一文读懂 Centos7 安装Hadoop3 单机版本&#xff08;伪分布式版本&#xff09; SpringBoot 2 集成Hive 3 pom.xml <?xml ver…

【SpringCloud】-GateWay源码解析

GateWay系列 【SpringCloud】-GateWay网关 一、背景介绍 当一个请求来到 Spring Cloud Gateway 之后&#xff0c;会经过一系列的处理流程&#xff0c;其中涉及到路由的匹配、过滤器链的执行等步骤。今天我们来说说请求经过 Gateway 的主要执行流程和原理是什么吧 二、正文 …

Bwapp学习笔记

1.基本sql语句 #求绝对值 select abs(-1) from dual; #取余数 select mod(10,3); #验证show databases结果是取之于schemata表的 show databases; select schema_name from information_schema.schemata; #查询当前的数据库 select database(); -- 查询数据库版本 s…

HTML5刷题笔记

在 HTML5 中&#xff0c;onblur 和 onfocus 是&#xff1a;事件属性 onblur 和 onfocus 属于焦点事件&#xff1a; onblur&#xff1a;失去焦点 onfocus&#xff1a;获取焦点 HTML5事件window 事件属性 针对 window 对象触发的事件&#xff1a; onafterprint script 文档…

Python入门学习篇(六)——for循环while循环

1 for循环 1.1 常规for循环 1.1.1 语法结构 for 变量名 in 可迭代对象:# 遍历对象时执行的代码 else:# 当for循环全部正常运行完(没有报错和执行break)后执行的代码1.1.2 示例代码 print("----->学生检查系统<------") student_lists["张三",&qu…

Python运算符函数化模块

文章目录 标准运算符替代函数实用工具itemgetterattrgettermethodcaller 刷完这60个标准库模块&#xff0c;成为Python骨灰级玩家 作为编程语言&#xff0c;如果无法做到Lisp的括号风格&#xff0c;那么必然羞于承认自己是函数式。python的lambda表达式以及各种生成式&#xf…

网络基础知识制作网线了解、集线器、交换机与路由器

目录 一、网线的制作 1.1、材料 1.2、网线的标准类别 二、集线器、交换机介绍 2.1、概念&#xff1a; 2.2、OSI七层模型 2.3、TCP/IP四层 三、路由器的配置 3.1、概念 3.2、四个模块 1、 网络状态 2、设备管理 3、应用管理 无人设备接入控制 无线桥接 信号调节…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)ChannelMap 模块的实现

&#xff08;三&#xff09;ChannelMap 模块的实现 这个模块其实就是为Channel来服务的&#xff0c;前面讲了Channel这个结构体里边它封装了文件描述符。假如说我们得到了某一个文件描述符&#xff0c;需要基于这个文件描述符进行它对应的事件处理&#xff0c;那怎么办呢&…

面试官:看你简历了解过并发,我们简单聊一聊

前言&#xff1a; 今天和大家探讨最近的面试题&#xff0c;好久没有面试了&#xff0c;所以在此记录一下。本篇文章主要讲解CyclicBarrier和CountDownLatch的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出&#xf…

HarmonyOS构建第一个ArkTS应用(FA模型)

构建第一个ArkTS应用&#xff08;FA模型&#xff09; 创建ArkTS工程 若首次打开DevEco Studio&#xff0c;请点击Create Project创建工程。如果已经打开了一个工程&#xff0c;请在菜单栏选择File > New > Create Project来创建一个新工程。 选择Application应用开发&a…

Jenkins自动化部署之后端

准备工作参考本人另外几篇Jenkins相关的文章 新建任务 添加参数配置 字符串参数&#xff1a;分支名称 多选框&#xff1a;项目名称&#xff08;Extended Choice Parameter插件必备&#xff0c;插件安装参考我另外的文章&#xff09; 这个分割规则自定义。只要根据Jenkins…

智能优化算法应用:基于爬行动物算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于爬行动物算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于爬行动物算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.爬行动物算法4.实验参数设定5.算法结果6.…

代码随想录-刷题第三十六天

435. 无重叠区间 题目链接&#xff1a;435. 无重叠区间 思路&#xff1a;本题与452. 用最少数量的箭引爆气球非常像&#xff0c;弓箭的数量就相当于是非交叉区间的数量&#xff0c;只要把弓箭那道题目代码里射爆气球的判断条件加个等号&#xff08;认为[0&#xff0c;1][1&am…

PostGreSQL:货币类型

货币类型&#xff1a;money money类型存储固定小数精度的货币数字&#xff0c;小数的精度由数据库的lc_monetary设置决定。windows系统下&#xff0c;该配置项位于/data/postgresql.conf文件中&#xff0c;默认配置如下&#xff0c; lc_monetary Chinese (Simplified)_Chi…

WARNING: HADOOP_SECURE_DN_USER has been replaced by HDFS_DATANODE_SECURE_USER.

Hadoop启动时警告&#xff0c;但不影响使用&#xff0c;强迫症的我还是决定寻找解决办法 WARNING: HADOOP_SECURE_DN_USER has been replaced by HDFS_DATANODE_SECURE_USER. Using value of HADOOP_SECURE_DN_USER.原因是Hadoop安装配置于root用户下&#xff0c;对文件需要进…

《PySpark大数据分析实战》-18.什么是数据分析

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

计算机网络——数据链路层-点对点协议(组成部分、PPP帧格式、透明传输、差错检测、工作状态)

目录 介绍 组成部分 PPP帧格式 透明传输 字节填充法 比特填充法 差错检测 工作状态 本篇我们介绍点对点协议PPP 介绍 点对点协议PPP&#xff08;Point-to-Point Protocol&#xff09;是目前使用最广泛的点对点数据链路层协议。 请大家想想看&#xff1a;一般的英特…