以下代码无法解码纬度和经度. 输出是:132, 1, 1645780273, 77276230, 0, -0.000000, 0.000000,对最后两个值纬度和经度进行了错误的转换. 如果我从 struct 中删除前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;
}

推荐答案

这与 struct 填充有关.

一般来说, struct 的成员从偏移量开始,偏移量是该成员大小的倍数,以便对齐.因此,在statlatitude个成员之间有4个填充字节,因此后者可以驻留在8的倍数的偏移量上.这意味着 struct 比你想象的大4字节.

如果可以,您应该重新排列构件,使它们以自然的偏移量对齐,这样构件之间就没有填充(尽管末端可能仍然有填充).

如果这不是一个选项,您可以使用特定于编译器的属性来打包 struct .如果您使用的是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;

另请注意,在某些体系 struct 上,未对齐的读取或写入可能会导致崩溃.

C++相关问答推荐

返回一个包含数组的 struct

有没有更简单的方法从用户那里获取数据类型来计算结果

当多个线程在C中写入相同的文件描述符时,如何防止争用情况?

无法用C++编译我的单元测试

如何跨平台处理UTF-16字符串?

fwrite无法写入满(非常大)缓冲区

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

Setenv在c编程中的用法?

在为hashmap创建加载器时,我的存储桶指向它自己

在C++中访问双指针

tick.q中的Kdb+键控表语法

==284==错误:AddressSaniizer:堆栈缓冲区下溢

覆盖读取函数,但当文件描述符为3或4时,我有问题

用C++构建和使用DLL的困惑

C++中PUTS函数的返回值

*S=0;正在优化中.可能是GCC 13号虫?或者是一些不明确的行为?

为什么argc和argv即使在主函数之外也能工作?

根据输入/输出将 C 编译过程分为预处理、编译、汇编和链接步骤

米斯拉映射到 klocwork 违规行为

C 初学者 - struct 中的字符串不需要 Malloc