柔性数组(C语言)

文章目录

  • 1. 柔性数组的定义
  • 2. 柔性数组的特点
  • 3. 柔性数组的使用
  • 4. 柔性数组的好处

也许你从来没有听说过 柔性数组这个概念,但是它确实是存在的。柔性数组是C语言中一种特殊的结构,它允许在结构体的末尾定义一个可变长度的数组。

1. 柔性数组的定义

柔性数组是在C99中的一种玩法,它有两种定义方式,当其中一种定义方式,编译器编译不通过的时候,可以换另一种方式。
方式一:

typedef struct st_type
{int i;int a[0];//柔性数组成员
}type_a;

方式二:

typedef struct st_type
{int i;int a[];//C99的玩法是:int a[]; 没有指定数组长度
}type_a;

2. 柔性数组的特点

  1. 结构中的柔性数组成员前面必须至少一个其他成员。

这是因为柔性数组的大小是不确定的,所以编译器需要知道其他成员的大小和偏移量。

  1. sizeof 返回的这种结构大小不包括柔性数组的内存。

这是因为柔性数组的大小是可变的,因此 sizeof 返回的是结构体的固定部分的大小。

  1. 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
struct S
{int a;char data[]; // 柔性数组成员
};struct S* str = malloc(sizeof(struct S) + 20); // 20是柔性数组的最大长度

在这里插入图片描述

3. 柔性数组的使用

以下代码,演示了柔性数组的用法:

#include <stdio.h>
#include <stdlib.h>struct S
{int n;int data[]; // 柔性数组成员
};int main() {// 创建包含柔性数组的结构体,并分配足够大的内存struct S* s = malloc(sizeof(struct S) + 20); // 20是柔性数组的最大长度if (s == NULL){perror("malloc");return 1;}s->n = 10;for (int i = 0; i < 5; ++i){(s->data)[i] = i;}for (int i = 0; i < 5; ++i){printf("%d ", (s->data)[i]);}free(s); // 释放内存s = NULL;return 0;
}

上面这段代码的意思是:我想分配一个不定长的数组,于是我有一个结构体,其中有两个成员,一个是n,一个是data。其实上述结构也可以通过指针运算和动态内存分配来实现。关于动态内存分配的知识,可以参考之前写的一篇文章:动态内存管理(malloc calloc realloc free)— C语言

#include <stdlib.h>
#include <string.h>// 定义结构体,包含柔性数组
struct S
{int len; // 柔性数组的长度int* data; // 柔性数组成员
};int main() 
{// 定义结构体指针struct S* s = (struct S*)malloc(sizeof(struct S));s->len = 5;// 给柔性数组的部分分配内存s->data = (int*)malloc(5 * sizeof(int)); // 假设柔性数组存储5个整数// 初始化柔性数组for (int i = 0; i < s->len; i++) {s->data[i] = i;}// 访问柔性数组的元素printf("柔性数组的内容: ");for (int i = 0; i < s->len; i++) {printf("%d ", s->data[i]);}printf("\n");// 释放内存free(s);s = NULL;return 0;
}

看到这里,你会说,把data声明成一个指针,然后为它再分配一下内存好像也可以也能完成我们预期的效果,那为什么还要搞出来一个0长数组呢?有啥意义呢?答案很简单,就是搞出来柔性数组,其实就是我们想给一个结构体内的数据分配一个连续的内存!

4. 柔性数组的好处

通过上面的介绍,我们知道柔性数组的存在就是想给一个结构体内的数据分配一个连续的内存!那这样做有什么好处呢?
第一个是,方便内存释放。

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

在使用柔性数组的时候,空间是一次性开辟好的,释放空间的时候只需要释放一次;而我们在模拟实现柔性数组的时候,是先给结构体开辟了空间,然后在结构体内进行了二次内存分配,因此在释放空间的时候也需要释放两次,然而释放的顺序也是有讲究的,要先释放data指向的空间,在释放结构体的空间,如果顺序反了,会导致data指向的空间无法被主动释放,会导致内存泄露。

在这里插入图片描述

第二个是,这样有利于访问速度。

连续的内存有益于提高访问速度,也有益于减少内存碎片。(其实,我个人觉得也没多高了,反正你跑不了要用做偏移量的加法来寻址)

  1. 含柔性数组的结构体在开辟空间的时候,是一次性开辟好的,在内存中是一片连续的空间。
    在这里插入图片描述

  2. 模拟含柔性数组的结构体在内存中是这样开辟空间的:
    在这里插入图片描述
    这种在内存中开辟空间的方式,可能会导致内存碎片的问题。内存碎片是指未被使用的小块内存,它们可能夹在已分配内存的中间,导致内存浪费。
    在这里插入图片描述
    而数据在内存中连续存储时,碎片化的可能性较低,因为数据被一起分配并存储。

至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。
创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !!!
在这里插入图片描述

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

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

相关文章

@ConditionalOnProperty 用法

文章目录 前言一、使用场景二、使用步骤1.错误示例2.ConditionalOnProperty的解决方案 总结 前言 ConditionalOnProperty 是Spring Boot中的条件注解&#xff0c;它的核心功能是通过属性名以及属性值来实现的&#xff0c;常被用于判断某个属性是否存在&#xff0c;然后决定某个…

商品API接口优秀案例 │ 国家电网办公物资电商化采购项目API解决方案

苏宁易购集团股份有限公司&#xff08;以下简称“苏宁”&#xff09;作为中国领先的O2O智慧零售商&#xff0c;在互联网、物联网、大数据盛行的时代&#xff0c;持续推进智慧零售和线上线下融合战略&#xff0c;全品类经营&#xff0c;全渠道运营&#xff0c;开放苏宁物流云、数…

asp.net老年大学信息VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio计算机毕业设计

一、源码特点 asp.net老年大学信息管理系统是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c# 语言开发 asp.net老年大学信息管理系统…

实习项目遇到的bug

问题1&#xff1a; 大概是因为没设置ts类型&#xff0c;它查不到的问题&#xff0c;不定义的话加上问号&#xff0c;加上可选链就不会报错了 {{bizEquipmentInfo.lastUnlockingVO?.lastUnlockingTime.replace(T, )? bizEquipmentInfo.lastUnlockingVO?.lastUnlockingTime.r…

【(数据结构) —— 顺序表的应用-通讯录的实现】

&#xff08;数据结构&#xff09;—— 顺序表的应用-通讯录的实现 一.通讯录的功能介绍1.基于动态顺序表实现通讯录(1). 功能要求(2).重要思考 二. 通讯录的代码实现1.通讯录的底层结构(顺序表)(1)思路展示(2)底层代码实现(顺序表&#xff09; 2.通讯录上层代码实现(通讯录结构…

idea中导入eclipse的javaweb项目——tomact服务(保姆级别)

idea中导入eclipse的javaweb项目——tomact服务&#xff08;保姆级别&#xff09; 1. 导入项目2. Project Settings下的各种配置步骤2.1 检查/修改 jdk 的引入2.2 配置Modules-Dependencies2.2.1 删掉eclipse相关的多余配置2.2.2 删掉jar包2.2.3 添加tomcat的依赖 2.3 配置Libr…

基于单目的光流法测速

目录 1.简介 2.代码实现 1.简介 基于单目的光流法是一种常见的计算机视觉技术&#xff0c;用于估计图像序列中物体的运动速度。它通过分析连续帧之间的像素变化来推断物体在图像中的移动情况。 背景&#xff1a; 光流法是计算机视觉领域中最早的运动估计方法之一&#xff0c…

HTML图片标签(2) HTML5+CSS3+移动web 前端开发入门笔记(三)

图片标签 HTML中&#xff0c;可以使用标签来插入图片。具体的语法为&#xff1a; <img src"图片路径" alt"替代文本">其中&#xff0c;src属性用于指定图片的路径&#xff0c;可以是相对路径或绝对路径。常见的有相对当前HTML文件的路径&#xff0…

【灵动 Mini-G0001开发板】+Keil5开发环境搭建+ST-Link/V2程序下载和仿真+4颗LED100ms闪烁。

我们拿到手里的是【灵动 Mini-G0001开发板】 如下图 我们去官网下载开发板对应资料MM32G0001官网 我们需要下载Mini—G0001开发板的库函数与例程&#xff08;第一手学习资料&#xff09;Keil支持包&#xff0c; PCB文件有需要的&#xff0c;可以自行下载。用户指南需要下载&a…

k8s 1.28版本二进制安装

本文目录 二进制安装Kubernetes&#xff08;k8s&#xff09;v1.28.0介绍1.环境1.0.环境准备1.Linux网卡没有eth0显示ens33或者其它&#xff08;以ens33为例&#xff09;方法一&#xff1a;修改网卡配置方法二&#xff1a;重新安装机器(本文为虚拟机) 2.克隆的虚拟机&#xff0c…

机器人控制算法——两轮差速驱动运动模型

1.Introduction 本文主要介绍针对于两轮差速模型的逆运动学数学推导。因为在机器人控制领域&#xff0c;决策规划控制层给执行器输出的控制指令v(车辆前进速度)和w(角速度)&#xff0c;因此&#xff0c;我们比较关心&#xff0c;当底层两个驱动电机接收到此信息&#xff0c;如何…

进化算法------代码示例

目录 前言代码示例1、寻找函数最大值2、句子匹配 前言 遗传算法就是在一个解空间上&#xff0c;随机的给定一组解&#xff0c;这组解称为父亲种群&#xff0c;通过这组解的交叉&#xff0c;变异&#xff0c;构建出新的解&#xff0c;称为下一代种群&#xff0c;然后在目前已有…

集成内部高端电源开关LTC3637HMSE、LTC3637MPMSE稳压器,TJA1443AT汽车CAN FD收发器。

一、LTC3637 76V、1A 降压型稳压器 &#xff08;简介&#xff09;LTC3637是一款高效率降压DC/DC稳压器&#xff0c;集成内部高端电源开关&#xff0c;功耗仅12μA DC&#xff0c;空载时可保持稳定的输出电压。LTC3637可提供高达1A的负载电流&#xff0c;并具有可编程峰值电流限…

【Redis】Java客户端使用zset命令

zadd/zrange zcard zrem zscore zrank

毅速丨模具3D打印材料有哪些选择

当前1.2709和CX是市面上最常用的3D打印模具钢材料&#xff0c;模具3D打印有没有更多的材料选择呢&#xff1f; 据了解&#xff0c;上海毅速推出的几款3D打印新材料正在被越来越多的行业所采用。如毅速的EM191S高性能高抛光不锈钢粉末&#xff0c;这款材料的抗开裂和耐腐蚀性能是…

Python学习基础笔记七十——模块和库1

模块和库&#xff1a; 一个python代码文件就实现了功能。功能比较单一。 在企业中&#xff0c;项目开发的文件&#xff0c;可能有成百上千个。 不同的代码文件&#xff0c;实现了不同的功能模块&#xff0c;就像一块块积木一样。这些功能文件整合起来&#xff0c;实现一个完…

javascript将html中的dom元素转图片

javascript将html中的dom元素转图片 百度网盘下载html2canvas.min.js&#xff1a; 全部文件-》js插件-》 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>网页中的某个区域转图片</title></head><body styl…

Django 使用Mysql数据库

目录 Django 使用Mysql数据库本地安装Mysql数据服务安装好Pymysql服务Django配置数据库迁移各种报错无法找到mysqlclient数据库拒绝连接 Django 使用Mysql数据库 本地安装Mysql数据服务 安装好Pymysql服务 python3 -m pip install PyMySQL官方文档介绍 Django配置 官网文档 …

Ubuntu中不能使用ifconfig命令

​ 问题 打开终端使用如下命令不能运行&#xff1a; ifconfig显示如下错误: 解决方法 在VMware中的虚拟机下面打开“编辑虚拟机设置”&#xff0c;或者在已经打开的虚拟机面板上面打开“虚拟机—设置” 选择网络适配器&#xff0c;选择“NAT模式”&#xff0c;没开机的就…

微软10月补丁 | 修复103个漏洞,包括2个零日漏洞,13个严重漏洞

近日&#xff0c;微软发布了2023年10月的补丁更新&#xff0c;解决了其软件中的103个漏洞。 在这103个漏洞中&#xff0c;有13个的评级为严重漏洞&#xff0c;90个被评为重要漏洞。自9月12日以来&#xff0c;谷歌已经解决了基于chrome的Edge浏览器的18个安全漏洞。 这两个零日…