我使用以下结构格式化CAN消息的数据。 messageData.ptr用于进一步处理。部分部分用于更好的访问。 问题是,为什么messageData.srcSpecifier和messageData.data
之间还有两个字节typedef union _MessagePureData_TypeDef
{
signed int S32[1];
unsigned int U32[1];
unsigned short U16[2];
signed short S16[2];
unsigned char U8[4];
} messagePureData;
typedef union _MessageData_TypeDef
{
unsigned char ptr[6];
struct
{
unsigned char srcDevice;
unsigned char srcSpecifier;
messagePureData data;
} section;
} messageData;
示例:
messageData.section.srcDevice = 0xAA;
messageData.section.srcSpecifier = 0xBB;
messageData.section.data.U32 = 0x11223344;
结果messageData.ptr包含: [0xAA,0xBB,0x01,0x17,0x44,0x33]
所以从哪里来的是0x01和0x17 ??
答案 0 :(得分:2)
对齐。
messagePureData
总是与int
对齐,大概可能是4个字节。这意味着section
肯定与8个字节对齐,在srcSpecifier
和data
之间放置两个填充字节(因此整个struct对象的对齐为8,data
为1 4)。另一方面,作为数组的ptr
是连续的,因此它覆盖与两个填充字节相同的存储空间。
| ptr | ptr + 1 | ptr + 2 | ptr + 3 | ptr + 4 | ptr + 5 |
| | | | | |
| srcDevice | srcSpecifier | padding | padding | &data | &data + 1 | ...
^ ^ ^
| Address is multiple of 8 | | Address is multiple of 4
|
|
| Address is a multiple of two;
| Unfeasible address for data.
你可以打包结构来绕过这个。
答案 1 :(得分:0)
由于联合包含int
个成员,因此它与int
具有相同的对齐要求。如果需要,在结构的data
成员之前添加填充以提供该对齐。
在您的平台上,似乎该要求是四个字节。在它之前的两个成员每个占用一个字节,因此需要两个以使其偏移量为四的倍数。这些不会初始化为任何特定值,因此如果您查看它们,您会看到任意值。
答案 2 :(得分:0)
messagePureData data
字段的大小为32位。
编译器因此通过添加2个字节(a.k.a. padding )将其与32位地址对齐。
您可以使用#pragma pack
来阻止编译器应用此重新对齐。
但请记住,访问此字段的汇编代码可能效率稍低。