柔性数组与不定长数据
一:什么是柔性数组
C99标准引入的一项特性,它允许你在一个结构体(struct
)的最后一个成员处,定义一个没有指定长度的数组。
例如:
typedef struct
{unsigned short cmd; // 命令字unsigned short len; // 长度unsigned int timestamp; // 时间戳unsigned char payload[]; // 数组指针
} data_ringbuff_ls_unit_t;
二:使用场景
主要用于将固定长度结构体头信息(命令字,长度等)和可变长的数据内容(payload)在内存中紧密地捆绑在一起。
这是最经典的用途,网络数据包通常由一个固定大小的包头(包含协议、长度、校验和等信息)和一个可变长度的负载(实际数据)组成。
另外许多文件格式(如图片、音频、自定义格式)都有一个文件头,后面跟着大量的数据。
三:使用方法
柔性数组使用常常伴随着动态内存分配(操作系统上常用方式),或者预先定义一片内存区域进行内存管理(单片机常用方式),申请一篇连续的内存区域,大小为柔性数组所在结构体大小 + 所要存储的数据长度;
// 1. 定义结构体
struct dynamic_string
{size_t length;char str[]; // 柔性数组成员
};const char *text = "Hello, World!";
size_t text_len = strlen(text) + 1; // +1 for null terminator// 2. 在堆上分配内存:结构体基础大小 + 字符串所需空间
struct dynamic_string *dyn_str = (struct dynamic_string *)malloc(sizeof(struct dynamic_string) + text_len * sizeof(char));
四:柔性数组不占据结构体长度
直接对柔性数组成员取
sizeof
:是非法的,会导致编译错误。对包含柔性数组的结构体取
sizeof
:得到的是结构体中除了柔性数组之外的所有固定成员的大小之和(并包含内存对齐的填充字节)。这个值是固定不变的。
// 结构体大小: 8字节(不包含payload[]的实际数据)
// 计算方式: sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned int) = 2 + 2 + 4 = 8
typedef struct
{unsigned short cmd; // 命令字unsigned short len; // 长度unsigned int timestamp; // 时间戳unsigned char payload[]; // 数组指针
} data_ringbuff_ls_unit_t;