柔性数组(详讲版)

目录

                  知识回顾:

一、什么是柔性数组

二、柔性数组的特点

三、柔性数组的使用

四、柔性数组与其他的比较

五、内存碎片

六、柔性数组的好处


知识回顾:

⭐有关柔性数组开辟动态内存管理的博文

C语言之动态内存管理篇(malloc和free、realloc、calloc)——优快云博客

⭐有关柔性数组中自定义类型的博文

C语言之自定义类型——优快云博客

一、什么是柔性数组

柔性数组即数组大小待定的数组,在 C 语言中可以在结构体的最后一个元素使用长度为 0 的数组来实现。

在 C 语言中,柔性数组是一种特殊的数组定义方式。它通常作为结构体的最后一个成员出现,其形式为一个未指定长度的数组类型。

也许你从来没有听说过柔性数组这个概念,但是它确实是存在的。C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做【柔性数组】成员。

其代码如下所示:

写法①:

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

注:有的编译器下写法①会报错

写法②:

Struct S
{
 int n;
 int arr[];//大小是未知的
};

二、柔性数组的特点

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

例如:

typedef Struct st_type
{
   int i;
   int a[0];//柔性数组成员
}type_a;
printf("%d\n",sizeof(type_a));//输出结果是4

三、柔性数组的使用

   在使用柔性数组时,需要我们手动开辟内存空间,并且对内存进行调整,我们用mallohenc进行内存的开辟,使用realloc对内存进行调整扩充。

struct S
{
	int n;
	int arr[0];//未知大小的数组 - 柔性数组成员
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 10*sizeof(int));
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	ps->n = 10;
	for (i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	free(ps);
	ps = NULL;
	return 0;
}

运行结果如下:

四、柔性数组与其他的比较

以下两段代码所要展现的效果是一样的,不过他们有不同的思路,下面来看柔性数组的应用代码:

Struct S
{
  int n;//所占大小为4个字节
  int arr[0];//大小未知
};
int main()
{
  //期望arr的大小是10个整形
  Struct S*ps=(Struct S*) malloc(sizeof(struct S)+10*sizeof(int));
 ps->n=10;
 int i=0;
for(i=0;i<10;i++)
{
  ps->arr[i]=i;
}
//增加、扩充
Struct S*ptr=(struct S*)realloc(ps,sizeof(struct S)+20*sizeof(int);
if(ptr!=NULL)
{
 ps=ptr;
}
//使用
//释放
free(ps);
ps=NULL;
return 0;
}

下面是用其他代码来编写的,其想要达成的效果一样:

Struct S
{
  int n;
  int arr[];
};
int main()
{
  Struct S*ps=(Struct S*)malloc(sizeof(struct S));
  if(ps==NULL)
  return 1;
  ps->n=10;
  ps->arr=(int*)malloc(10*sizeof(int));
  if(ps->arr==NULL)
  return 1;
  int i=0;
  for(i=0;i<10;i++)
{
  ps->arr[i]=i;
}
//扩容
 int * ptr=(int*)realloc(ps->arr,20*sizeof(int));
if(ptr!=NULL)
{
  ps->arr=ptr;
}
  return 0;
}

   注: 这种方法虽然也达到了实现了相应的功能,但是和第一种相比还是有很多不足,这里我们不是用柔性数组开辟的空间,而是用指针的方式申请的空间内存,这里我们用到了两次malloc,两次malloc对应两次free,这样的场景下容易出错。而上面包含柔性数组的方式malloc的次数更少一些,更不容易出错,相对来说更好。 

五、内存碎片

 内存碎片是指在计算机内存分配过程中产生的不连续的、无法被有效利用的内存空间。 当我们在申请堆空间的时候,空间与空间之间的间隔,也就是内存碎片。

六、柔性数组的好处

第一:方便内存释放

使用柔性数组可以在一次内存分配中同时为结构体和柔性数组分配空间。这样可以简化内存管理,减少分配和释放内存的次数,提高程序的效率。由于柔性数组的长度可以在运行时根据实际需求进行调整,所以可以很方便地适应不同大小的数据。

第二:有利于提高访问速度

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

### 柔性数组的概念 柔性数组是一种特殊的数组形式,在 C99 标准中被正式引入。它可以作为结构体的最后一个成员,用于实现动态分配内存的功能,从而灵活管理数组的实际大小[^1]。 柔性数组的特点在于其长度不需要在定义时明确指定,这使得它能够适应不同的数据需求场景。通常情况下,普通的数组需要在声明时就确定大小,而柔性数组则突破了这一限制,成为一种动态数组的形式[^2]。 --- ### 结构体中的柔性数组定义 柔性数组必须位于结构体的最后位置,并且它的前面至少有一个其他类型的成员变量。以下是典型的柔性数组结构体定义: ```c struct FlexibleArray { int size; // 存储实际数组的大小 int data[]; // 柔性数组成员 }; ``` 在这个例子中,`data` 是一个柔性数组,表示该数组的具体大小将在运行时决定[^3]。 --- ### 柔性数组的使用方法 为了使用柔性数组,需要手动为其分配足够的内存空间。具体操作如下: #### 动态内存分配 由于柔性数组本身并不占用任何存储空间,因此可以通过 `malloc` 或 `calloc` 函数为整个结构体分配内存,其中要考虑到柔性数组所需的额外字节数量。 假设我们需要创建一个包含 10 个整数的柔性数组,则可以这样分配内存: ```c #include <stdio.h> #include <stdlib.h> #define ARRAY_SIZE 10 int main() { struct FlexibleArray *fa = malloc(sizeof(struct FlexibleArray) + sizeof(int) * ARRAY_SIZE); if (fa == NULL) { printf("Memory allocation failed\n"); return -1; } fa->size = ARRAY_SIZE; for (int i = 0; i < fa->size; ++i) { fa->data[i] = i * 2; // 填充数据 } printf("Data in flexible array:\n"); for (int i = 0; i < fa->size; ++i) { printf("%d ", fa->data[i]); } printf("\n"); free(fa); // 释放内存 return 0; } ``` 上述代码展示了如何动态分配内存给带有柔性数组的结构体实例,并对其填充和访问数据[^4]。 --- ### 注意事项 1. **不可初始化**:柔性数组无法像普通数组那样直接赋初值。 2. **仅限于结构体最后一项**:柔性数组只能作为结构体的最后一部分存在。 3. **兼容性问题**:虽然柔性数组是在 C99 中标准化的特性,但在某些较旧本的编译器上可能不受支持。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值