你真的了解C语言中的【柔性数组】吗~

柔性数组

  • 1. 什么是柔性数组
  • 2. 柔性数组的特点
  • 3. 柔性数组的使用
  • 4. 柔性数组的优势

1. 什么是柔性数组

也许你从来没有听说过柔性数组这个概念,但是它确实是存在的。
C99中,结构体中的最后⼀个元素允许是未知大小的数组,这就叫做柔性数组成员

例如:

struct S
{int i;int arr[];//柔性数组成员
};

2. 柔性数组的特点

  • 结构体中的柔性数组成员前面必须至少有一个其他成员
  • sizeof返回的这种结构体大小不包括柔性数组的内存。
  • 包含柔性数组成员的结构体用malloc函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

例如:

#include <stdio.h>struct S
{int i;int arr[];//柔性数组成员
};int main()
{int sz = sizeof(struct S);printf("%d\n", sz);return 0;
}

输出结果:

在这里插入图片描述

3. 柔性数组的使用

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>struct S
{int i;int arr[];//柔性数组成员
};int main()
{//struct S s;//只申请了4字节空间,柔性数组没有申请空间struct S* ps=(struct S*)malloc(sizeof(struct S) + 40);//40字节是给柔性数组开辟的if (ps == NULL){printf("%s\n", strerror(errno));return 1;}//使用ps->i = 100;int i = 0;for (i = 0; i < 10; i++){ps->arr[i] = i;}for (i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}//调整空间,柔性数组柔性的体现struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 80);if (ptr != NULL){ps = ptr;ptr = NULL;}//……//释放free(ps);ps = NULL;return 0;
}

当前代码的内存布局如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/391dc6b00d254d6d8af2e3542019c372.png

思考:有人会想到那为什么那为什么不直接让结构体成员为int* ,然后动态开辟一块空间给int* 指向呢?

代码实现如下:

#include <stdio.h>
#include <stdlib.h>struct S
{int n;int* arr;
};int main()
{struct S*ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){return 1;}ps->n = 100;ps->arr = (int*)malloc(40);if (ps->arr == NULL){return 1;}//使用int i = 0;for (i = 0; i < 10; i++){ps->arr[i] = i;}for (i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}//扩容int* ptr = (int*)realloc(ps->arr, 80);if (ptr != NULL){ps->arr = ptr;}//释放free(ps->arr);free(ps);ps = NULL;return 0;
}

内存布局如图所示:

在这里插入图片描述

在结构体中这两种方式都能实现“柔性”的效果(空间可调整),哪一种方式更好呢?我们进行对比:

在方式1中使用柔性数组时,n和arr的空间只要使用一次malloc就可以全部开辟,最后一次free就可以释放。

而方式2中struct需要一次malloc开辟,arr又需要malloc开辟,最后也要2次free才可以释放

我们知道使用malloc的次数越多,如果忘记了free,则就越容易造成内存泄漏,其次就是如果在内存中频繁的进行malloc,则形成的内存碎片也越多,这样会使内存的利用率更低。

4. 柔性数组的优势

  1. 方便内存释放
    如果我们的代码是在⼀个给别人用的函数中,你在里面做了⼆次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存⼀次性分配好了,并返回给用户⼀个结构体指针,用户做⼀次free就可以把所有的内存也给释放掉。

  2. 这样有利于访问速度
    连续的内存有益于提高访问速度,也有益于减少内存碎片。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot整合Kafka

文章目录 1. 介绍2. Kafka基础2.1. 安装KafKakafka集群搭建_kafka交流群-CSDN博客 3. Spring Boot整合Kafka3.1. 引入Kafka依赖3.2.编写配置文件 4. 生产者&#xff08;produced&#xff09;4.1. 生产者基础案例(基础测试) 5. 消费者5.1.消费者基本案例(基础测试) 6.Kafka常用配…

python 公共函数及操作符使用示例合集

python公共操作符以及方法是什么 在Python中&#xff0c;公共操作通常指的是那些可以对不同数据类型&#xff08;如数字、字符串、列表、元组、字典等&#xff09;进行操作的通用函数或方法。这些操作符或函数通常是内置的&#xff0c;并且可以在Python的官方文档中找到。 主要…

数字电路 第五章—第四节(顺序脉冲发生器)

一、计数型顺序脉冲发生器 1、电路组成 计数型顺序脉冲发生器一般都是按自然态序计数的二进制计数器和译码器组成。 2、输出4个脉冲的顺序脉冲发生器 &#xff08;1&#xff09;逻辑电路图&#xff08;采用JK触发器&#xff09;&#xff1a; &#xff08;2&#xff09;时序图…

二叉搜索树的范围和(Lc938)——DFS

给定二叉搜索树的根结点 root&#xff0c;返回值位于范围 [low, high] 之间的所有结点的值的和。 示例 1&#xff1a; 输入&#xff1a;root [10,5,15,3,7,null,18], low 7, high 15 输出&#xff1a;32示例 2&#xff1a; 输入&#xff1a;root [10,5,15,3,7,13,18,1,nul…

家居清洁必备:2024如何挑选高效家用洗地机的实用指南

对于养宠物的家庭来说&#xff0c;宠物的毛发无处不在&#xff0c;尤其在换毛季节&#xff0c;清理工作更加繁琐。此时&#xff0c;洗地机的出现为解决这些问题提供了便利。洗地机可以同时扫地和拖地&#xff0c;实现高效清洁&#xff0c;减轻了清洁负担。而且&#xff0c;洗地…

【爬虫逆向实战 逆向滑块 Python+Node】今天逆向的网站有点嘿嘿,还是仅供学习,别瞎搞

逆向日期&#xff1a;2024.03.01 使用工具&#xff1a;Node.js、Python 加密方法&#xff1a;AES标准算法 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标准算…

windows系统安装《植物大战僵尸2009原版》教程

本文演示如何在windows免费安装 植物大战僵尸2009原版。 首先到 点此下载安装包 此页面最末端下载百度网盘分享的安装包。 下载完成后安装如下步骤进行安装&#xff1a; 安装完成即可开心的玩耍啦&#xff01; 我自己的安装过程录屏在这里 https://www.bilibili.com/vid…

新 Logo 正式发布,Tubi 品牌全面升级!

作为新一代观众的首选流媒体平台&#xff0c;Tubi 持续扩大自身影响力&#xff0c;并于近日推出了富有活力的新品牌形象。 根据 Nielsen 的 The Gauge 报告&#xff0c;Tubi 在 2024 年 1 月的电视总观看份额提升至 1.5%&#xff0c;在年轻人和多元化观众群体中的吸引力持续上升…

MYSQL--JDBC优化

一.JDBC优化: 优化前提: 有时候我们并不清楚某些表当中一共有多少列,以及这些列的数据类型,这个时候我们就需要提前通过一些方法提前了解到这些数据,从而更好的进行输出 具体语句: package cn.jdbc;import java.sql.*;public class JDBCDEmo1 {public static void main(String…

11.盛最多水的容器

题目&#xff1a;给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 解题思路&#xff1a;可以…

2023 re:Invent AI 生成产品体验,从 Bedrock 到 Amazon Q

引 如果你也有如下问题&#xff0c;那么接下来的文字会一一为你解答 一套数据集&#xff0c;如何微调不同类型的开源大模型&#xff1f;—— Bedrock 如何只有产品说明书&#xff0c;如何构建一个智能问答机器人&#xff1f;—— Q 哪里还有免费的 GPU 算力——在线 Jupyter…

JQMobile Loader Widget 遮罩层改造

最近在用jqmobile 做一个混合APP项目时候用到 jqmobile1.4.3提供的Loader Widget控件,但是这个控件本身是一个loading弹出层,这个弹出层弹出之后,用户还是可以去点击按钮,重复发送请求,为了防止重复提交,我想了两种办法, 1,在loading弹出层弹出之后,让按钮不可用.但是form表单…

DC28V270V转AC36V115V航空逆变器

在当今的航空航天电源行业中&#xff0c;DC28V270V转AC36V115V航空逆变器发挥着至关重要的作用。作为一种关键的逆变器电源设备&#xff0c;DC28V270V转AC36V115V航空逆变器不仅在航空领域有着广泛的应用&#xff0c;还在许多其他领域发挥着重要作用。 一、DC28V270V转AC36V11…

源码的角度分析Vue2数据双向绑定原理

什么是双向绑定 我们先从单向绑定切入&#xff0c;其实单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新。那么双向绑定就可以从此联想到&#xff0c;即在单向绑定的基础上&#xff0c;用户更新…

GoFrame:如何简单地搭建一个简单地微服务

一切资料来源于GoFrame官网, 感兴趣的, 可以直接去官网查阅相关资料。 首先下载框架工具, 下载地址:https://github.com/gogf/gf/releases 然后进入你想要放置的项目文件夹, 执行命令行 gf init {project_name} #project_name为你的项目名 执行完后项目结构如图所示 然…

Java ElasticSearch-Linux面试题

Java ElasticSearch-Linux面试题 前言1、守护线程的作用&#xff1f;2、链路追踪Skywalking用过吗&#xff1f;3、你对G1收集器了解吗&#xff1f;4、你们项目用的什么垃圾收集器&#xff1f;5、内存溢出和内存泄露的区别&#xff1f;6、什么是Spring Cloud Bus&#xff1f;7、…

Java构造方法总结(很清晰)

构造方法扫盲&#xff1a;构造方法就是为了创建对象的 解释&#xff1a;真正创建对象的是 new 这个关键字&#xff0c;Java 虚拟机在创建对象时是有很多步骤的&#xff0c;构造方法只是其中的一步&#xff0c;它的作用是进行成员变量初始化。

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境等应用

原文链接&#xff1a;AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境等应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Di…

强大而灵活的python装饰器

装饰器&#xff08;Decorators&#xff09; 一、概述 在Python中&#xff0c;装饰器是一种特殊类型的函数&#xff0c;它允许我们修改或增强其他函数的功能&#xff0c;而无需修改其源代码。装饰器在函数定义之后立即调用&#xff0c;并以函数对象作为参数。装饰器返回一个新…

微信小程序云开发教程——墨刀原型工具入门(安装以及基础使用教程)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…