在嵌入式世界中,我们经常拥有通过固定长度缓冲区传递的数据结构。使用这样的东西相对容易处理:
#define TOTAL_BUFFER_LENGTH 4096
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
};
static_assert(sizeof(struct overlay) <= TOTAL_BUFFER_LENGTH);
struct overlay* overlay = malloc(TOTAL_BUFFER_LENGTH);
也就是说,我们使用数据结构作为覆盖层,以允许轻松访问当前正在使用的缓冲区部分。
然而,我们有许多缓冲区格式,它们也使用缓冲区的最后几个字节来存储校验和等内容。我们目前使用这样的结构:
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
char reserved[TOTAL_BUFFER_LENGTH -
sizeof(uint16_t) - sizeof(uint16_t) -
(sizeof(uint8_t) * ARY1_LEN) -
sizeof(uint32_t)];
uint32_t crc;
};
这个简单的数据结构看起来很丑陋,但当结构增长到有几十个字段时,这绝对是一个怪物。这也是可维护性的噩梦,因为添加或删除结构字段意味着reserved
必须同时更新大小计算。
当结构的末尾只包含一项(如校验和)时,我们有时会使用辅助函数来读取/写入值。这使数据结构保持干净和可维护,但是当缓冲区的末尾有多个字段时,它不能很好地扩展。
如果我们可以做这样的事情会很有帮助:
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
char reserved[TOTAL_BUFFER_LENGTH -
offsetof(struct overlay, reserved) -
sizeof(uint32_t)];
uint32_t crc;
};
不幸的是,offsetof
仅适用于完整的对象类型,并且由于它位于 的定义的中间,因此struct overlay
该类型还不完整。
有没有一种更清洁、更易于维护的方式来做这种事情?我基本上需要一个固定长度的结构,在开头和结尾都有字段,中间的剩余空间保留/未使用。