你真的了解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. 这样有利于访问速度
    连续的内存有益于提高访问速度,也有益于减少内存碎片。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DiskMirror-spring-boot-starter 技术|

DiskMirror-spring-boot-starter 技术 diskMirror 实现了 SpringBoot 的 starter 能够集成到 SpringBoot 中。 DiskMirror 的 starter&#xff0c;通过引入此类&#xff0c;可以直接实现 diskMirror 在 SpringBoot 中的自动配置&#xff0c;接下来我们将使用案例逐步的演示 d…

AI视频又又炸了!照片+声音变视频,阿里让Sora女主唱歌小李子说rap

Sora之后&#xff0c;居然还有新的AI视频模型&#xff0c;能惊艳得大家狂转狂赞&#xff01; 有了它&#xff0c;《狂飙》大反派高启强化身罗翔&#xff0c;都能给大伙儿普法啦&#xff08;狗头&#xff09;。 这就是阿里最新推出的基于音频驱动的肖像视频生成框架&#xff0c;…

马斯克正式起诉OpenAI和奥特曼!

就在刚刚&#xff0c;马斯克闹出来一件大事——正式起诉OpenAI和Sam Altman&#xff0c;并要求OpenAI 恢复开源GPT-4等模型&#xff01; 众所周知&#xff0c;马斯克这两年一只在推特上指责 OpenAI是CloseAI(不开源)&#xff0c;但都只是停留在口头上。 而这次马斯克动了真格。…

搭建LNMP环境并搭建论坛和博客

目录 一、LNMP架构原理 二、编译安装Nginx 三、编译安装MySQL 四、编译安装PHP 五、配置Nginx支持PHP解析 六、安装论坛 七、安装博客 一、LNMP架构原理 LNMP架构&#xff0c;是指在Linux平台下&#xff0c;由运行Nginx的web服务器&#xff0c;运行PHP的动态页面解析程序…

聚道云软件连接器2月新增应用/产品更新合集

2月更新概要 新增应用&#xff1a; 应用1&#xff1a;旺店通 应用2&#xff1a;明道云 应用3&#xff1a;春雨医生 应用4&#xff1a;姿美堂 应用5&#xff1a;三维家 新增&更新功能 1、【流程】中增加版本管理功能 新增应用 应用1&#xff1a;旺店通 旺店通ERP隶…

38.云原生之Istio安全-流量鉴权加密

云原生专栏大纲 文章目录 TLS 和 mTLSTLS 和 mTLS使用场景TLS 加密通信的流程终止 TLS什么时候用 mTLS&#xff1f;什么时候不用 mTLS&#xff1f; 流量加密入口流量加密内部流量加密PeerAuthentication 为工作负载设置 mTLSDestinationRule 为工作负载设置 mTLS 安全最佳实战…

(定时器/计数器)中断系统(详解与使用)

讲解 简介 定时器/计数器 定时器实际上也是计数器,只是计数的是固定周期的脉冲 定时和计数只是触发来源不同(时钟信号和外部脉冲)其他方面是一样的。 定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值…

Qt应用软件【测试篇】vargrid内存检查工具

文章目录 vargrid介绍vargrid官网vargrid安装常用命令Valgrind的主要命令vargrid介绍 Valgrind是一个用于构建动态分析工具的框架,能自动检测许多内存管理和线程错误,并详细分析程序性能。Valgrind发行版包括七个成熟工具:内存错误检测器、两个线程错误检测器、缓存和分支预…

防御保护课程笔记

内容安全 防病毒 过滤技术 密码学

基于java ssm springboot+VUE疫情防疫系统系统前后端分离设计和实现

基于java ssm springbootVUE疫情防疫系统系统前后端分离设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐…

vue3使用百度地图实现个性化地图和轨迹

vue3使用百度地图实现个性化地图和轨迹 最终效果如图&#xff1a; 步骤如下&#xff1a; 一、百度地图在vue3中的引入 1.首先在百度地图开发中心中申请ak&#xff08;不多介绍&#xff09; 2.两种引入方式&#xff1a;在 index.html 中直接引入&#xff1b;使用npm导包。&…

【已亲测有效】如何彻底删除nodejs,避免影响安装新版本

第一步开始菜单搜索uninstall node.js&#xff0c;点击之后等待删除&#xff08;删除node_modules文件夹以及以下这些文件&#xff09; 第二步手动删除nodejs下载位置的其他文件夹。&#xff08;就是另外自己新建的两个文件夹node_cache和node_global&#xff09; 到这里其实应…

GEE:计算NDVI时间序列和谐波拟合曲线之间的残差时间序列

作者:CSDN @ _养乐多_ 本文将介绍在谷歌地球引擎(Google Earth Engine)使用 Landsat 时间序列数据数据进行时间序列谐波(harmonic)拟合建模,并对模型的残差(residual)序列(计算NDVI时间序列和谐波拟合曲线之间的残差时间序列)进行分析。具体流程为使用Landsat计算ND…

MariaDB MaxScale实现mysql8读写分离

目录 1.MaxScale 是干什么的&#xff1f; 2.MaxScale 实验环境 3.实现数据库主从复制 4.创建用户 1) 创建监控用户 2) 创建路由用户 5.docker 安装MaxScale 6.配置maxscale 使用 maxctrl list servers 命令查看运行状态 查看注册服务 使用 maxctrl list listeners Read-…

I/O:标准IO(二)

一、标准IO操作函数 1.fgets、fputs int fputs(const char *s, FILE *stream); 功能描述&#xff1a;将字符串s写入stream指向的文件中 返回数&#xff1a;成功写入文件中数据的字节数 int puts(const char* s) 功能描述&#xff1a;将字符串s写入终端&#xff1b; 返回值&…

kitex 入门和基于grpc的使用

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于kitex系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系…

动态规划--(算法竞赛、蓝桥杯)--二维费用背包

1、B站视频链接&#xff1a;E15 背包DP 二维费用背包_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; int f[101][101]; //f[j][k]第i件物品&#xff0c;体积<j,重量<k的最大价值int main(){int n,V,W;//物品、容量、承重int v,w,val;//体积、重…

redis实现分布式全局唯一id

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1 使用 Redis 计数器实现2.2 使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1 导入依赖配置3.2 配置yml文件3.3 序列化配置3.4 编写获取工具3.5 测试获取工具 四、运行结果 一、前言 在很…

施耐德M340和M200 Modbus 通讯实现

Unity平台下M340和M200通过Modbus TCP通讯 两者通过RJ45连接&#xff0c;M340内IO scanning配置&#xff1a; IP address是各个M200的地址&#xff0c;通过这个配置&#xff0c;可以将各server的指定数据区映射到M340的内部数据区。 相比于M200作Modbus TCP Client&#xff0…

Java SE 1.基础常识

1.计算机语言 1.机器语言&#xff1a; 二进制的0和1组成的编码2.汇编语言&#xff1a; 英文标识符组成的编码3.高级语言&#xff1a; 接近自然语言 2.Java技术平台 1.JAVA SE 1.Java Platform Standard Edition&#xff0c;Java标准版 1.JDK 1.Java开发工具集&#xff1a;包括J…