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

C语言柔性数组详解

目录

1.柔性数组

2.柔性数组的特点 

3.柔性数组的使用 

4.柔性数组的优势 


1.柔性数组

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

struct S
{char c;int n;int arr[];//柔性数组
};
struct S
{char c;int n;int arr[0];//柔性数组
};

有些编译器支持a[0]这种写法,有些编译器支持a[ ]这种写法,具体取决于编译器。


2.柔性数组的特点 

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

例如:

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

运行结果:


3.柔性数组的使用 

代码1:结构体里放数组

#include<stdio.h>
#include<stdlib.h>
struct S
{int n;int arr[0];//柔性数组
};
int main()
{//期望数组可以存放5个元素struct S* ps=(struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));if (ps == NULL){perror("malloc");return 1;}ps->n = 100;int i = 0;for (i = 0; i < 5; i++){ps->arr[i] = i;}//调整空间//期望数组可以存放10个元素struct S* ptr=(struct S*)realloc(ps, sizeof(struct S) + 10 * sizeof(int));if (ptr != NULL){ps = ptr;}//使用//释放free(ps);ps = NULL;return 0;
}

通过realloc函数调整空间使数组变大变小,从而使柔性的特点更加鲜明,也不难想到它放在结构体中最后一个元素的原因。 

内存窗口:


4.柔性数组的优势 

代码2:结构体里放指针

#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){perror("malloc");return 1;}ps->arr =(int*) malloc(5 * sizeof(int));if (ps->arr == NULL){perror("malloc");return 1;}//使用ps->n = 100;int i = 0;for (i = 0; i < 5; i++){ps->arr[i] = i;}//调整数组大小int*ptr =(int*)realloc(ps->arr, 10 * sizeof(int));if (ptr != NULL){ps->arr = ptr;}//使用//释放  注意:释放两块空间的先后顺序!free(ps->arr);ps->arr = NULL;free(ps);ps = NULL;return 0;
}

 

注意:释放两块空间的先后顺序!如果先释放ps指向的内存空间,就找不到arr的值了,导致arr指向的内存空间无法释放。所以,要先释放arr指向的数组,再释放ps指向的内存。

上述代码1和代码2可以完成同样的功能,但是代码1的实现有两个好处

1.方便内存释放 

代码2里面做了二次内存分配,结构体内的成员也需要free,用户需要做两次free把内存释放掉,并且需要注意释放内存的顺序,而代码1用户做一次free就可以把所有的内存给释放掉。

2.有利于提高访问速度

连续的内存有益于提高访问速度,也有益于减少内存碎片


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

相关文章:

  • 自动驾驶---视觉Transformer的应用
  • 预训练语言模型实践笔记
  • Perl 哈希
  • Linux之Mysql索引和优化
  • springboot业务逻辑写在controller层吗
  • Ubuntu 24.04 LTS 桌面安装MT4或MT5 (MetaTrader)教程
  • Go基础编程 - 12 -流程控制
  • 汽车信息安全--TLS,OpenSSL
  • 深入探索 SQL 中的 LIKE 右模糊匹配(LIKE RIGHT)与左模糊匹配(LIKE LEFT)
  • mybatis 多数据源 TDataSource required a single bean, but 2 were found
  • Dubbo SPI 之路由器
  • Python深度学习环境配置(Pytorch、CUDA、cuDNN),包括Anaconda搭配Pycharm的环境搭建以及基础使用教程(保姆级教程,适合小白、深度学习零基础入门)
  • 月影护眼大路灯怎么样?书客|月影|霍尼韦尔超硬核实力性能测评pk!
  • 邮件安全篇:邮件传输加密(SSL/TLS or STATRTTLS)
  • 【系统架构设计 每日一问】三 Redis支持事务么,Redis的事务如何保证
  • 【中项】系统集成项目管理工程师-第4章 信息系统架构-4.3应用架构
  • DasViewer打开Revit输出的fbx格式的模型,为啥一团黑?
  • 【05】LLaMA-Factory微调大模型——初尝微调模型
  • Training for Stable Diffusion
  • 初学51单片机之指针基础与串口通信应用
  • 【启明智显分享】甲醛检测仪HMI方案:ESP32-S3方案4.3寸触摸串口屏,RS485、WIFI/蓝牙可选
  • Linux 驱动学习笔记
  • ip地址设置了重启又改变了怎么回事
  • layui table 浮动操作内容收缩,展开
  • Ubuntu24.04 NFS 服务配置
  • vue3使用html2canvas
  • OpenCV分水岭算法watershed函数的使用
  • laravel为Model设置全局作用域
  • Leetcode之string
  • OS:处理机进程调度