当前位置: 首页 > news >正文

【C语言】深入理解柔性数组:特点、使用与优势分析

C语言学习

柔性数组
友情链接:C语言专栏


文章目录

  • C语言学习
  • 前言:
  • 柔性数组
  • 一、柔性数组的特点
  • 二、柔性数组的使用
  • 三、柔性数组的优势
  • 总结
  • 附录
    • 上文链接
    • 专栏


前言:

在有结构体和动态内存分配的知识后,今天咱们来说说柔性数组吧!!!


柔性数组

C99 中,结构中的最后⼀个元素允许是未知大小的数组,这就叫做柔性数组成员。
例如:

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

有些编译器会报错⽆法编译可以改成:

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

一、柔性数组的特点

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

示例:

struct S
{int i;int a[];//柔性数组成员
};
int main()
{printf("%d\n", sizeof(struct S));//输出的是4return 0;
}

输出:
在这里插入图片描述

二、柔性数组的使用

//代码1
#include<stdio.h>
#include<stdlib.h>
struct S
{int i;int a[];//柔性数组成员
};
int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));//动态开辟内存:4+20个字节//4个字节为i,20个字节为数组if (ps == NULL)//判断是否开辟成功{perror("malloc failed");exit(EXIT_FAILURE);  }//使用:ps->i = 100;for (int i = 0; i < 5; i++){ps->a[i] = i;}//增加空间reallocstruct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 10 * sizeof(int)); //给数组增加20个字节(5个元素)if (tmp == NULL)//判断是否开辟成功{perror("malloc failed");exit(EXIT_FAILURE);}ps = tmp;//继续由ps管理这块内存;tmp = NULL;//使用//……//释放free(ps);ps = NULL;return 0;
}

三、柔性数组的优势

上述的结构也可以设计为别的结构,也能完成同样的效果。

//代码2
#include<stdio.h>
#include<stdlib.h>
struct S
{int i;int* a;//通过指针指向一块空间,实现与柔性数组相同的效果
};
int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));//动态开辟内存一个struct S大小的空间if (ps == NULL)//判断是否开辟成功{perror("malloc failed");exit(EXIT_FAILURE);}ps->i = 100;ps->a = (int*)malloc(5 * sizeof(int)); //动态开辟内存5个int大小的空间,并将起始地址给aif (ps->a == NULL)//判断是否开辟成功{perror("malloc failed");exit(EXIT_FAILURE);}//使用for (int i = 0; i < 5; i++){ps->a[i] = i;}//增加空间reallocint* tmp = (int*)realloc(ps->a, sizeof(10 * sizeof(int)));//给ps->a指向的空间增加20个字节(5个元素)if (tmp == NULL)//判断是否开辟成功{perror("malloc failed");exit(EXIT_FAILURE);}ps->a  = tmp;tmp = NULL;//使用//……//释放//注意先后顺序free(ps->a );ps->a  = NULL;free(ps);ps = NULL;return 0;
}

上述代码1和代码2可以完成同样的功能,但是代码1的实现有两个好处:
第一个好处是:方便内存释放

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

第二个好处是:这样有利于访问速度

连续的内存有益于提高访问速度,也有益于减少内存碎片。图示:
在这里插入图片描述


总结

柔性数组是C99标准引入的重要特性,它允许在结构体的末尾定义一个长度可变的数组。通过结合动态内存管理,柔性数组能够高效地处理不确定大小的数据集合,是C程序员进阶必备技能之一。

附录

上文链接

《动态内存分配避坑指南:六大易错点解析与经典笔试题实战》

专栏

C语言专栏

http://www.lryc.cn/news/592279.html

相关文章:

  • MySQL安装包安装方法
  • Vue (Official) v3.0.2 新特性 为非类npm环境引入 globalTypesPath 选项
  • 28、鸿蒙Harmony Next开发:不依赖UI组件的全局气泡提示 (openPopup)和不依赖UI组件的全局菜单 (openMenu)、Toast
  • ModbusRTU转profibus网关与涡街液体流量计通讯读取流量计温度
  • 回归预测 | MATLAB实现SA-BP模拟退火算法优化BP神经网络多输入单输出回归预测
  • jvm分析篇---1、先认识下dump文件
  • Kubernetes Pod 深度理解
  • 【C语言进阶】题目练习(2)
  • Composer 可以通过指定 PHP 版本运行
  • uni-app 跳转外部连接
  • 网络原理——UDP
  • 如何 ASP.NET Core 中使用 WebSocket
  • html复习
  • 【收集电脑信息】collect_info.sh
  • 电脑插上u盘不显示怎么回事
  • 分表聚合助手类
  • 分布式面试点
  • RecyclerView与ListView深度对比分析
  • 从复合变量到分组分析:piecewiseSEM 解析生态系统多因子交互作用
  • UDP 协议下一发一收通信程序的实现与解析
  • Linux 定时任务全解析:atd 与 crond 的区别及实战案例(含日志备份 + 时间写入)
  • AugmentCode还没对个人开放?
  • 双通达信多板块同步
  • 如何抉择HTTPSProxy?
  • AR技术重塑电力巡检:效率提升与智能升级
  • 三维重建一: 相机几何
  • 基于ROS2进行相机标定,并通过测试相机到棋盘格之间的距离进行验证
  • Go语言实战案例-斐波那契数列生成器
  • 9. isaacsim4.2教程-ROS加相机/CLOCK
  • pgsql导出导入超过50G数据、解决方法