我已经在这一段时间了,这真的让我很困惑.这是一个非常精简的代码片段,可以重现这个问题:
uint8_t dataz[] = { 1, 2, 3, 4, 5, 6 };
struct mystruct {
uint8_t dummy1[1];
uint16_t very_important_data;
uint8_t dummy2[3];
} *mystruct = (void *) dataz;
printf("%x\n", mystruct -> very_important_data);
Run Code Online (Sandbox Code Playgroud)
你期望什么应该是输出?我会说x302,但不是.它给了我x403.与使用此结构相同:
struct mystruct {
uint8_t dummy1[2];
uint16_t very_important_data;
uint8_t dummy2[2];
} *mystruct = (void *) dataz;
Run Code Online (Sandbox Code Playgroud)
你会怎么解释?
正如其他人所提到的,除非您的编译器对齐是字节对齐的,否则您的结构可能会有"漏洞".编译器这样做是因为它加速了内存访问.
如果你正在使用gcc,那么有一个"packed"属性会导致struct被字节对齐,所以删除"holes":
struct __attribute((__packed__)) mystruct {
uint8_t dummy1[1];
uint16_t very_important_data;
uint8_t dummy2[3];
} *mystruct = (void *) dataz;
Run Code Online (Sandbox Code Playgroud)
但是,这不一定能解决问题.16位值可能未设置为您认为应该的值,具体取决于计算机的字节顺序.您将不得不在结构中的任何多字节整数中交换字节.没有通用的功能,因为它需要在运行时有关结构布局的信息,而C不提供.
将结构映射到二进制数据通常是不可移植的,即使您现在可以在机器上运行它.