
一. 定义
定义数组时,没有指明其长度,此为弹性数组。
二. 使用条件
弹性数组只能存在于结构体中,并且必须满足如下条件:
- 弹性数组必须为结构体的最后一个成员;
- 该结构体必须包含一个非弹性数组的成员;
- 编译器需要支持 C99 标准。
三. 示例
声明一个学生信息结构体,其中包含学号,年级,学生姓名。
typedef struct {
int32_t id;
int32_t grade;
int8_t name[];
}struct_info_struct;
其中的 int8_t name[]
即为弹性数组。因为学生的姓名有长有短。如果定义为固定长度,会造成空间浪费。
四. 使用方法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct {
int32_t id;
int32_t grade;
int8_t name[];
}student_info_struct;
int main() {
int32_t *tmp = 0;
int8_t *name = "sdc";
student_info_struct *si = NULL;
printf("sizeof(struct) = %dn", sizeof(student_info_struct));
si = (student_info_struct *)malloc(sizeof(student_info_struct) + strlen(name) + 1); // +1 是为了存储 '0'
if(NULL == si)
{
printf("malloc failedn");
return -1;
}
memset((void *)si, 0, sizeof(student_info_struct) + strlen(name) + 1);
si->id = 123;
si->grade = 6;
memcpy((void *)si->name, name, strlen(name));
printf("addr:n");
printf("si: 0x%pn", si);
printf("si->grade: 0x%pn", &si->grade);
printf("si->name: 0x%pn", &si->name);
printf("si->name: 0x%pn", si->name);
return 0;
}
结果:
sizeof(struct) = 8
addr:
&si: 0x00000000003C21C0
&si->grade: 0x00000000003C21C4
&si->name: 0x00000000003C21C8
si->name: 0x00000000003C21C8
说明:
- 通过
sizeof(struct) = 8
可以看出,弹性数组在结构体中不占用空间。所以&si->name
和si->name
的值相同; - 代码第 19 行的
malloc
申请了sizeof(student_info_struct) + strlen(name) + 1
大小的空间。其中strlen(name) + 1
是为si->name
分配的; - 结构体
si
在内存中的数据:

五. 用途
弹性数组主要用于存储不定长数据,比如上例中的学生姓名。 我用弹性数组来存储串口数据,比如接收北斗或 GPS 模块数据。这两者的数据都不是定长的,每次收到相应的帧以后,根据帧中的『长度』字段来分配空间。
六. 参考
以下链接中给出了弹性数组的其他实现方式,用于不支持弹性数组的编译器中。
https://riptutorial.com/c/example/10850/flexible-array-members
https://www.geeksforgeeks.org/flexible-array-members-structure-c/
http://c-faq.com/struct/structhack.html