c语言-柔性数组


前言

本篇文章介绍c语言中的柔性数组。


一、柔性数组的介绍

1.1 柔性数组的定义

在定义一个结构体类型时,结构体的最后一个成员变量允许为一个没有大小的数组时,这个数组称为柔性数组。
注意点:柔性数组成员必须是结构体成员的最后一个成员
例如,下面定义一个拥有柔性数组的结构体类型
方式一:

struct S
{
   
   
	int n;
	int arr[0];  //数组大小未知,柔性数组
};

方式二:

struct S
{
   
   
	int n;
	int arr[];  //数组大小未知,柔性数组
};

二、柔性数组的使用

2.1 使用说明

  • sizeof返回的包含柔性数组的结构体的大小时,返回值不包括柔性数组的大小。
  • 包含柔性数组的结构体使用malloc()函数进行动态内存的分配,并且分配的内存大小应该大于结构体的大小,以适应柔性数组的预期大小。
  • 可以使用realloc()函数修改柔性数组的大小。

2.2 结构体中的成员只包含一个柔性数组成员

结构体定义:

//结构体成员只存在柔性数组成员
struct Single_S
{
   
   
	int arr[0];
};

使用malloc()为柔性数组分配空间

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
   
   
	struct Single_S* ps = (struct Single_S*)malloc(20);
	if (NULL == ps)
	{
   
   
		printf("%s\n", strerror(errno));
		return 1;
	}
	
<think> 柔性数组(Flexible Array Member,简称FAM)是C99标准引入的特性,它允许在结构体的末尾定义一个长度未指定的数组。这种数组的大小在结构体定义时并不确定,而是在动态分配内存时通过分配足够大的内存来容纳结构体本身和数组所需的额外空间。 ### 柔性数组的特性 1. **定义位置**:柔性数组必须是结构体的最后一个成员。 2. **语法**:在声明时,数组的方括号内为空(或者可以写0,但C99标准推荐留空)。 3. **内存分配**:使用`malloc`等动态内存分配函数为结构体分配内存时,需要额外分配数组所需的空间。 4. **内存连续性**:结构体和柔性数组的内存是连续的,因此可以直接通过数组名访问数组元素。 ### 柔性数组的语法 ```c struct flex_array_struct { int length; double data[]; // 柔性数组 }; ``` ### 使用步骤 1. 定义包含柔性数组的结构体。 2. 计算需要分配的内存大小:`sizeof(结构体) + 数组长度 * sizeof(数组元素类型)`。 3. 使用`malloc`分配内存。 4. 使用柔性数组。 5. 使用完后,释放内存。 ### 示例代码 ```c #include <stdio.h> #include <stdlib.h> // 定义包含柔性数组的结构体 struct flex_array_struct { int length; double data[]; // 柔性数组 }; int main() { int n = 5; // 数组长度为5 // 分配内存:结构体大小 + n个double的大小 struct flex_array_struct *arr = malloc(sizeof(struct flex_array_struct) + n * sizeof(double)); if (arr == NULL) { perror("malloc"); return 1; } arr->length = n; // 给数组赋值 for (int i = 0; i < n; i++) { arr->data[i] = i * 1.1; } // 打印数组 for (int i = 0; i < arr->length; i++) { printf("arr->data[%d] = %.2f\n", i, arr->data[i]); } // 释放内存 free(arr); return 0; } ``` ### 柔性数组的优点 1. **内存连续**:结构体和数组在内存中是连续的,减少内存碎片,提高访问效率(缓存友好)。 2. **节省空间**:相比使用指针指向一个单独分配的数组,柔性数组只需要一次分配和一次释放,且不需要额外的指针存储空间。 3. **方便内存管理**:只需要一次`malloc`和一次`free`。 ### 柔性数组与指针的区别 在C语言中,我们也可以使用指针来动态分配数组,例如: ```c struct pointer_struct { int length; double *data; }; ``` 但这种方式需要两次内存分配(一次为结构体,一次为数组)和两次释放,而且结构体和数组的内存不连续。同时,这种结构会多占用一个指针的空间(通常4或8字节)。 ### 注意事项 1. **C99标准**:柔性数组是C99标准引入的,确保编译器支持C99或更高版本。 2. **结构体大小**:使用`sizeof`计算结构体大小时,柔性数组的大小不计入。例如,`sizeof(struct flex_array_struct)`只包含`length`成员的大小(可能包含对齐填充),不包含柔性数组的空间。 3. **不能定义多个柔性数组**:一个结构体只能有一个柔性数组,且必须是最后一个成员。 ### 相关问题§§: 1. 柔性数组在C99之前是如何模拟实现的? 2. 柔性数组与动态分配的指针数组在性能上有何差异? 3. 柔性数组能否作为函数参数传递?如何传递? 4. 在C++中是否支持柔性数组?如果不支持,如何实现类似功能? </think> ### C语言柔性数组特性 柔性数组(Flexible Array Member,FAM)是C99标准引入的特性,允许在结构体的最后一个成员定义一个未指定大小的数组。这种数组的大小在结构体定义时不确定,而是在动态分配内存时确定。 #### 关键特性: 1. **定义语法**: ```c struct flex_array { int size; char data[]; // 柔性数组声明(方括号为空) }; ``` 2. **内存分配**: 使用 `malloc` 动态分配内存时,需额外分配数组所需空间: ```c struct flex_array *fa = malloc(sizeof(struct flex_array) + 100 * sizeof(char)); ``` - `sizeof(struct flex_array)`:包含除柔性数组外的结构体大小 - `100 * sizeof(char)`:柔性数组的实际空间 3. **访问方式**: 直接通过成员名访问: ```c fa->size = 100; for (int i = 0; i < 100; i++) { fa->data[i] = 'A' + (i % 26); // 像普通数组一样使用 } ``` ### 为什么需要柔性数组? 1. **内存连续性**: - 结构体与数组在内存中连续存储(减少内存碎片) - 提高缓存命中率(CPU读取效率更高) 2. **对比传统方案**: 传统方案(指针 + 二次分配): ```c struct legacy { int size; char *data; // 需要额外分配 }; struct legacy l = malloc(sizeof(struct legacy)); l->data = malloc(100 * sizeof(char)); // 二次分配 ``` - ❌ 两次分配/释放操作 - ❌ 内存不连续 - ❌ 多占用一个指针空间(8字节) 3. **资源管理简化**: - 单次 `malloc/free` 即可管理整个结构 - 避免内存泄漏风险 ### 完整示例代码 ```c #include <stdio.h> #include <stdlib.h> // 柔性数组结构体 struct flex_array { int size; char data[]; // 柔性数组 }; int main() { int arr_size = 10; // 动态分配(结构体 + 数组空间) struct flex_array *fa = malloc(sizeof(struct flex_array) + arr_size * sizeof(char)); fa->size = arr_size; // 初始化数组 for (int i = 0; i < arr_size; i++) { fa->data[i] = 'A' + i; } // 打印验证 printf("Size: %d\n", fa->size); for (int i = 0; i < arr_size; i++) { printf("data[%d] = %c\n", i, fa->data[i]); } free(fa); // 单次释放所有内存 return 0; } ``` ### 注意事项 1. **C99要求**:编译器需支持C99及以上标准(如 GCC 加 `-std=c99`) 2. **唯一性**:柔性数组必须是结构体最后一个成员 3. **禁用静态分配**: ```c struct flex_array fa; // 错误!无法确定数组大小 ``` 4. **大小计算**: `sizeof(struct flex_array)` 不包含柔性数组的空间
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值