如何解决用标准便携式C 方法替换紧凑结构的“__attribute__ ((packed))”
将几个值转换为用于无线电传输的字节串必须避免不需要的字节。在 ARM 目标(32 位)上使用 GCC 我使用“属性((打包))”。该指令是基于 GCC 的(正如我在此处读到的),因此通常不可移植 - 我更喜欢。示例:
typedef struct __attribute__ ((packed)) {
uint8_t u8; // (*)
int16_t i16; // (*)
float v;
...
uint16_t cs; // (*)
}valset_t; // valset_t is more often used
valset_t vs;
(*) 值将使用 4 个字节而不使用 ((packed)) 属性,而不是根据需要使用一两个字节。用于传输的按字节访问:
union{
valset_t vs; // value-set
uint8_t b[sizeof(valset_t)]; // byte array
}vs_u;
使用 vs_u.b[i] .
- 处理时间在这里并不重要,因为传输速度要慢得多。
- 此处也不考虑 Endian,但在某些情况下可能会应用不同的 C 编译器。
- 此任务的前辈帖子提供了一些见解,但也许同时在 C 中改进了打包和对齐功能?c)。
是否有更便携的 C 语言解决方案来执行此任务?
解决方法
包装/填充不是标准化的,因此严格来说结构/联合是不可移植的。 #pragma pack(1)
更常见一些,并且被许多不同的编译器(包括 gcc)支持,但它仍然不是完全可移植的。
另请注意,存在填充是有原因的,这些具有非标准包装的结构在某些系统上可能是危险的或不必要的低效。
用于存储协议等的唯一 100% 可移植数据类型是 unsigned char
数组。如果您为它们编写序列化器/反序列化器例程,您只能获得完全可移植的结构。这自然是以额外代码为代价的。反序列化示例:
valset_t data_to_valset (const unsigned char* data)
{
valset_t result;
result.something = ... ;
...
return result;
}
如果存在某种网络字节序,您可以在同一例程中将网络字节序转换为 CPU 字节序。
请注意,您必须像上面的函数示例一样输入它。您不能编写如下代码:
unsigned char data[n] = ... ;
valset_t* vs = (valset_t*)data; // BAD
这在很多方面都很糟糕:对齐、填充、严格别名、字节序等等。
不过也可以反过来,使用 unsigned char*
逐字节检查或序列化结构体。但是,这样做仍然不能解决填充字节或字节序的问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。