我正在尝试将字节数组复制到结构中:
实际字节数:
00000000 | ff 53 4d 42 72 00 00 00 00 08 01 c8 00 00 00 00 | .SMBr...........
目的地结构:
typedef struct {
uint8_t protocol[4];
uint8_t command;
uint32_t status;
uint8_t flags;
uint16_t flags2;
uint16_t pidHigh;
uint16_t somethingElse;
} MyStruct;
但由于某种原因,myStruct.status
中的字节不是它们应该是的字节:
printf("%x", bytes[4]);
=> 72 // Ok
printf("%x", myStruct.command);
=> 72 // Ok
printf("%02x%02x%02x%02x", bytes[5], bytes[6], bytes[7], bytes[8]);
=> 00000000 // Ok
printf("%"PRIX32, myStruct.status);
=> C8010800 // What?! Why did it take the next 4 bytes... and reversed them?
用于复制这些字节的代码:
MyStruct myStruct;
memcpy(&myStruct, bytes, 16);
此代码在ARM(iPhone 5)上运行,这可能解释了输出的小端性,但它没有解释为什么在复制的字节中有+4字节的偏移量。
这里发生了什么?
答案 0 :(得分:2)
结构的内存布局将符合其成员的对齐要求。在32位ARM上,16位值需要2字节对齐,32位和更大值需要4字节对齐。当对齐方式彼此不匹配时,结构元素之间存在填充字节。由于这种填充,将字节数组复制或转换为结构不会像预期的那样工作。
不幸的是,没有什么好办法解决这个问题。您可以选择打包您的结构,这可能会降低其性能。您可以单独复制每个元素。或者您可以仔细安排您的结构,以便它们紧密包装(假设您了解代码将运行的所有平台的对齐规则)。
例如:如果你以这种方式重新排列结构,它将完美地填充中间或末尾没有填充字节(它是4的偶数倍)。
typedef struct {
uint32_t status; // +0
uint16_t flags2; // +4
uint16_t pidHigh; // +6
uint16_t somethingElse; // +8
uint8_t command; // +10
uint8_t flags; // +11
uint8_t protocol[4]; // +12
} MyStruct;
答案 1 :(得分:0)
编译器对齐struct中的元素,以便所有这些元素占用内存中等于4的倍数的空间。
所以基本上,command
,据说只使用1个字节,然后是status
之前的3个字节的垃圾。
您可以通过设置:
告诉编译器不要这样做#pragma pack(1)