【C】柔性数组详解

简介: 柔性数组详解




🎈今日心语:前途很重要,身体同样重要


目录


柔性数组

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

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

例如:

struct
{
  int n;
  float s;
  int arr[];//柔性数组成员//是结构体的成员变量,但是是数组
};
int main()
{
  return 0;
}

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

struct
{
  int n;
  float s;
  int arr[0];//这里做了改动,柔性数组成员
};
int main()
{
  return 0;
}

1.1 柔性数组的特点:

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

例如:

struct S
{
  int n;//4
  float s;//4 结构中的柔性数组成员前面必须至少一个其他成员。
  int arr[];//柔性数组成员
};
int main()
{
  printf("%d\n",sizef(struct S));//输出的结果是8  sizeof返回的结构大小不包括柔性数组的内存
}

1.2 柔性数组的使用

#include<stdio.h>
#include<stdlib.h>
struct S
{
  int n;//4
  float s;//4 结构中的柔性数组成员前面必须至少一个其他成员。
  int arr[];//柔性数组成员//是结构体的成员变量,但是是数组
};
int main()
{
  //printf("%d\n",sizef(struct S));//8  sizeof返回的结构大小不包括柔性数组的内存
  //struct S s;//不包含arr柔性数组的空间,这时就需要借助malloc来开辟空间
  //为柔性数组arr开辟4个整型元素的连续空间
  struct S* ps = (struct S*)malloc(sizeof(struct S) + sizeof(int) * 4);
  //检查
  if (ps == NULL)
  {
        //……
    return 1;
  }
  //使用
  ps->n = 100;
  ps->s = 5.5f;
  int i = 0;
  for (i = 0; i < 4; i++)
  {
    scanf("%d", &(ps->arr[i]));
  }
  printf("%d %f\n", ps->n, ps->s);
  for (i = 0; i < 4; i++)
  {
    printf("%d", ps->arr[i]);
  }
  //修改柔性数组成员arr的内存空间
  struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 5 * sizeof(int));
  if (ptr != NULL)
  {
    ps = ptr;
    ptr = NULL;
  }
  //……使用
  //释放
  free(ps);
  ps = NULL;

运行结果:


1.3 柔性数组的优势

上述的struct结构也可以设计为:

//代码2//结构体包含一个指针,指针指向malloc开辟的空间
struct S
{
  int n;
  float s;
  int* arr;//arr指向的空间malloc,数据都放在堆上以保持和上面代码一致
};
int main()
{
  struct S* ps = (struct S*)malloc(sizeof(struct S));
  if (ps == NULL)
    return 1;
  ps->n = 100;
  ps->s = 5.5f;
  int* ptr = (int*)malloc(4 * sizeof(int));
  if (ptr == NULL)
  {
    return 1;
  }
  else
  {
    ps->arr = ptr;
  }
  //使用
  int i = 0;
  for (i = 0; i < 4; i++)
  {
    scanf("%d", &(ps->arr[i]));
  }
  //调整空间
   //……relloc
   //打印
  printf("%d\n", ps->n);
  printf("%f\n", ps->s);
  for (i = 0; i < 4; i++)
  {
    printf("%d ", ps->arr[i]);
  }
  //释放
  free(ps->arr);
  ps->arr = NULL;
  free(ps);
  ps = NULL;
  return 0;
}

上述代码1代码2可以实现同样的功能,但是方法1的实现有两个好处:

  • 第一个好处是:方便内存释放

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

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

方法2,struct开辟的空间和malloc开辟的空间不一定是连续的,会有内存碎片(内存与内存之间的间隙)

方法1,一次性将struct内部的结构体成员的空间都开辟好了,是一块连续的空间

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

扩展阅读:

C语言结构体里的数组和指针


结语:

这里我们关于柔性数组的内容就介绍完了,
文章中某些内容我们之前有介绍,所以只是一笔带过,还请谅解。
希望以上内容对大家有所帮助👀,如有不足望指出🙏


加油!!




相关文章
|
6月前
|
编译器 C语言
柔性数组理解
柔性数组理解
45 0
|
编译器 C语言 Python
柔性数组
柔性数组
44 0
|
程序员 C语言 C++
动态内存管理与柔性数组2
动态内存管理与柔性数组
49 0
|
6月前
|
编译器 C语言
C语言中柔性数组的讲解与柔性数组的优势
C语言中柔性数组的讲解与柔性数组的优势
|
编译器 C语言 C++
动态内存分配(3)——柔性数组
动态内存分配(3)——柔性数组
|
6月前
|
编译器
关于柔性数组
关于柔性数组
|
存储 算法 程序员
【C/C++】动态内存&柔性数组
【C/C++】动态内存&柔性数组
128 0
|
编译器 C语言
认识柔性数组
认识柔性数组
|
6月前
|
编译器 C语言