C语言【柔性数组】

简介: C语言【柔性数组】

🫅什么是柔性数组

也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。

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


struct S
{
  char ch;
  int arr[];
  //int arr[0];
};

柔性数组:


1.结构体的最后一个成员

2.数组的大小有两种表现形式:(1)不写(2)写成 0。编译器总有一个可以通过


🫅柔性数组的使用

柔性数组的特点:


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

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

3.包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

为什么柔性数组成员前面必须至少一个其他成员??它是有依赖性的吗??数组大小不进行说明的话,那么结构体的大小是多少呢??这个柔性数组有什么优势啊??


🌰(验证含有柔性数组的结构体的大小)

#include<stdio.h>
struct S
{
  int a;
  char arr[];
};
int main()
{
  printf("%d\n", sizeof(struct S));
  return 0;
}
//运行结果:
*****
4
*****

🐉🐉🐉🐉🐉

嗯???应该比4还大啊,因为还有char数组啊。难道结构体大小不包括柔性数组的大小?


原因就是:结构体的大小不包括柔型数组成员的大小,因为数组的大小是未知的,它的空间的开辟主要是用动态开辟的。它的柔性就体现在这里,数组的大小不是固定的,可根据用户需要来增大缩小。

🌰(柔型数组的使用)


#include<stdio.h>
#include<stdlib.h>
struct S
{
  int a;
  char arr[];
};
int main()
{
  //创立结构体变量,柔性数组的大小为10
  struct S* ptr = (struct S*)malloc(sizeof(struct S)+ 10 * sizeof(char));
  if (ptr == NULL)
  {
    perror("malloc->ptr");
    return 1;
  }
  //使用
  ptr->a = 100;
  for (int i = 0; i < 10; i++)
  {
    //打印十个h
    ptr->arr[i] = 'h';
  }
  //打印
  for (int i = 0; i < 10; i++)
  {
    printf("%c ", ptr->arr[i]);
  }
  //增容
  struct S* ph = (struct S*)realloc(ptr, sizeof(struct S) + 20 * sizeof(char));
  if (ph == NULL)
  {
    perror("ph");
  }
  else
  {
    ptr = ph;
    //使用
    //...
    //释放空间
    free(ptr);
    ptr = NULL;
  }
  return 0;
}
//运行结果
*****
h h h h h h h h h h
*****

🐉🐉🐉🐉🐉

为什么动态开辟要这样写啊?


struct S* ptr = (struct S*)malloc(sizeof(struct S)+ 10 * sizeof(char)) ---------- malloc里面分两部分:结构体的大小(不包含柔型数组成员)和 要柔性数组的大小。

这样写的一个好处就是:使得这两块内存块是连续的。内存空间是连续的,效率就快。

这样就可以理解为什么“结构中的柔性数组成员前面必须至少一个其他成员”。那是因为柔性数组的大小不包含于结构体的大小。如果结构体中只有柔型数组一个成员,那么此结构体就不存在。


🫅柔性数组的优势

看到这里,有人就有疑问;我不用柔型数组也可以实现上面的程序。

🌰(模拟实现柔性数组)


//模拟实现柔性数组
#include<stdio.h>
#include<stdlib.h>
struct S
{
  int a;
  char* ph;
};
int main()
{
  //创建结构体变量
  struct S* ptr = (struct S*)malloc(sizeof(struct S));
  if (ptr == NULL)
  {
    perror("malloc->ptr");
    return 1;
  }
  //使用
  ptr->a = 100;
  //开辟柔性数组的空间,柔性数组的大小为10
  ptr->ph = (char*)malloc(sizeof(char) * 10);
  for (int i = 0; i < 10; i++)
  {
    //打印十个h
    ptr->ph[i] = 'h';
  }
  for (int i = 0; i < 10; i++)
  {
    printf("%c ", ptr->ph[i]);
  }
  //增容
  char* p = (char*)realloc(ptr->ph, sizeof(char) * 20);
  if (p == NULL)
  {
    perror("realloc->p");
    return 1;
  }
  //使用
  //...
  //释放
  free(ptr->ph);
  ptr->ph = NULL;
  free(ptr);
  ptr = NULL;
  //在这里,一定要注意:
  //要先释放ph的空间,不要先释放掉ptr的空间
  //因为:你把ptr释放掉,就找不到ph了
  return 0;
}

跟柔性数组相比:


柔性数组:

动态开辟(malloc)一次

释放空间(free)一次

内存空间连续

模拟实现:

动态开辟(malloc)两次

释放空间(free)两次

内存空间不连续

由此,可以得出柔性数组的优势:


方便内存释放

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

有利于访问速度.

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

扩展阅读:

-C语言结构体里的数组和指针 https://coolshell.cn/articles/11377.html,在这篇文章里面,也详细地介绍了柔性数组的相关知识,不懂得可以进去看看。

e5799cc381694af6bf42674ff96b5845.jpeg


相关文章
|
编译器 程序员 测试技术
详解动态内存管理【malloc/calloc/realloc/free函数/柔性数组】【C语言/进阶/数据结构基础】
详解动态内存管理【malloc/calloc/realloc/free函数/柔性数组】【C语言/进阶/数据结构基础】
209 0
|
编译器 程序员 C语言
【C语言】动态内存管理(malloc,free,calloc,realloc,柔性数组)
【C语言】动态内存管理(malloc,free,calloc,realloc,柔性数组)
|
7月前
|
C语言
C语言(14)----柔性数组
C语言(14)----柔性数组
38 1
|
6月前
|
程序员 C语言 C++
【C语言】:柔性数组和C/C++中程序内存区域划分
【C语言】:柔性数组和C/C++中程序内存区域划分
43 0
|
7月前
|
存储 安全 编译器
【C语言】动态内存管理 -- -- 深入了解malloc、calloc、realloc、free、柔性数组(万字深入了解)
【C语言】动态内存管理 -- -- 深入了解malloc、calloc、realloc、free、柔性数组(万字深入了解)
78 0
【C语言】动态内存管理 -- -- 深入了解malloc、calloc、realloc、free、柔性数组(万字深入了解)
|
7月前
|
程序员 编译器 C语言
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(下)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
47 0
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(下)
|
7月前
|
编译器 数据库 C语言
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(上)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
49 0
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(上)
|
6月前
|
编译器 C语言
C语言探索旅程之【柔性数组】
C语言探索旅程之【柔性数组】
39 0
|
7月前
|
C语言
【C语言】柔性数组(可变长数组)
【C语言】柔性数组(可变长数组)
|
7月前
|
C语言 C++
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free(中)
C语言进阶⑰(动态内存管理)四个动态内存函数+动态通讯录+柔性数组_malloc+free
42 0