首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C语言中的伸缩型数组:看似简单,其实很巧妙

C语言中的伸缩型数组:看似简单,其实很巧妙

原创
作者头像
李述铜
发布2025-10-27 15:25:52
发布2025-10-27 15:25:52
630
举报
文章被收录于专栏:C语言C语言

继续写我在阅读《C Primer Plus》时,看到的有意思的内容。

这篇文章主要介绍C99中新增的特性:伸缩性数组成员

问题示例

我们在做嵌入式通信的协议解析时,往往会定义一个包结构体用来描述通信所用的数据包。通常情况下,每次传输的数据包大小并不保证完全相同;所以,我们往往会按最大包长度来定义相应的包结构体。比如:

代码语言:javascript
复制
typedef struct {
    uint8_t cmd;
    uint16_t len;
    uint8_t payload[MAX_PAYLOAD_LEN];
} packet_t;

当然,也有些人采用这样的方式去定义:

代码语言:javascript
复制
typedef struct {
    uint8_t cmd;
    uint16_t len;
    uint8_t payload[1];
} packet_t;

无论是上述哪种方法,实际都显得不够优雅。毕竟它实际负载的有效长度既不是MAX_PAYLOAD_LEN也不是1.甚至于在有些情况下,有些包并没有负载。

那么,真正标准、优雅、可移植的写法是什么?

这里就引出了本篇文章要介绍的特殊结构体成员:伸缩型数组成员(Flexible Array Member)

什么是伸缩型数组成员

简单来说,伸缩型数组成员是一个数组,且位于结构体的最后位置。例如,我们可以改写上述包结构,采用伸缩型数组成员。

代码语言:javascript
复制
typedef struct {
    uint8_t cmd;
    uint16_t len;
    uint8_t payload[];  // 注意,这里没有写长度!
} packet_t;

其中,payload就是“伸缩型数组成员”。

值得注意的是,payload[]中并没有给出长度值,而是留空。这就意味着该成员不会在结构体里占空间,真正的长度由运行时再决定

上面这段话是什么意思呢?我们可以结合下面的例子来理解。

应用示例

比如,我们现在要创建一个命令包,负载长度为len。为了给这个包分配空间,我们可以采用如下的方法来完成:

代码语言:javascript
复制
size_t total = sizeof(packet_t) + len;
packet_t *pkt = malloc(total);

pkt->cmd = CMD_PING;
pkt->len = len;
memcpy(pkt->payload, data, len);

首先,sizeof(packet_t)计算出来的结构,并不会把payload的大小算在内。也就是说,虽然payload位于结构体内部,但它占用的空间相当于是0字字节

其次,我们如果仍然可以使用pkt->payload对负载空间进行访问。

我们可以用下面的图来更加形像的理解以上两点:

  • 求包头的长度非常简单:只需要使用sizeof(packet_t)即可计算得出
  • 可以灵活地创建不同长度的数据包:只需要使用malloc(sizeof(packet_t) + len)即可。

使用注意事项

如果我们要在实际项目中使用伸缩型数组成员,必须遵循以下三点原则:

  • 必须是结构体最后一个成员:因为伸缩型数组成员不占用存储空间
  • 数组的声明方式类似于普通数组,只不过方括号中的内容为空。

下面给出了一个错误的示例,在该示例中,buf位于结构体中间,这将导致编译器编译失败。

代码语言:javascript
复制
typedef struct {
    int len;
    char buf[];		// 错误:伸缩数组必须在最后
    int type;  
} data_t;


作者介绍

李述铜,嵌入式系统与底层架构领域讲师,专注于操作系统、CPU 架构、RTOS 内核与系统软件实现原理的教学与研究。 出版作品《从0手写x86计算机操作系统》,在嵌入式教育领域拥有多年实战教学经验。

主讲课程包括:《从0手写嵌入式操作系统》《从0手写TCP/IP协议栈》《从0手写FAT32文件系统等》。课程以底层原理为核心、以可操作性为导向,帮助工程师系统理解软件与硬件之间的联系,从“能用”迈向“能造”。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题示例
    • 什么是伸缩型数组成员
    • 应用示例
  • 使用注意事项
  • 作者介绍
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档