以下代码无法解码纬度和经度。
输出为:132, 1, 1645780273, 77276230, 0, -0.000000, 0.000000
,对最后两个值纬度和经度进行了错误的转换。
如果我删除前 4 个值并从结构中删除 uint32_t identifiers;
我得到正确的结果 132, 1, 1645780273, 77276230, 0, 59.877871, 10.465200
非常感谢任何有助于理解这种行为的帮助。
#include <stdio.h>
#include <string.h>
int main() {
union {
unsigned char bytes[36];
struct{
uint32_t identifier;
uint16_t telegram_size;
uint16_t telegram_version;
uint32_t seconds;
uint32_t nanoseconds;
uint32_t stat;
double latitude;
double longitude;
}unpack;
}telegram;
unsigned char values[] = {0x23, 0x4B, 0x4D, 0x42, 0x84, 0x00, 0x01, 0x00, 0x31, 0x9d, 0x18, 0x62, 0x46, 0x24, 0x9b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x3e, 0x2c, 0x11, 0x5e, 0xf0, 0x4d, 0x40, 0xCA, 0x32, 0xC4, 0xB1, 0x2E, 0xEE, 0x24, 0x40};
memcpy(telegram.bytes, values, 36);
for (int i=0;i<36;i++){
printf("%02X ", telegram.bytes[i]);
}
printf("\n%u, %u, %u, %u, %u, %f, %f\n", telegram.unpack.telegram_size, telegram.unpack.telegram_version, telegram.unpack.seconds, telegram.unpack.nanoseconds, telegram.unpack.stat, telegram.unpack.latitude, telegram.unpack.longitude);
return 0;
}
最佳答案
这与结构填充有关。
一般来说,结构的成员从偏移量开始,该偏移量是该成员大小的倍数,用于对齐目的。因此,stat
和 latitude
成员之间有 4 个填充字节,因此后者可以驻留在 8 的倍数的偏移量处。这意味着结构是比你想象的大 4 个字节。
如果可以,您应该重新排列成员,使它们以自然偏移对齐,这样成员之间就没有填充(尽管最后可能仍然有填充)。
如果这不是一个选项,您可以使用特定于编译器的属性来打包结构。如果您使用 gcc,您将执行以下操作:
struct __attribute__((__packed__)) {
uint32_t identifier;
uint16_t telegram_size;
uint16_t telegram_version;
uint32_t seconds;
uint32_t nanoseconds;
uint32_t stat;
double latitude;
double longitude;
}unpack;
另请注意,在某些架构上,未对齐的读取或写入可能会导致崩溃。
关于c - union 无法解码字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71271541/