1.我有以下结构。
typedef struct
{ unsigned int ibaseRecord;
unsigned int irecordNumber;
unsigned char brecordType;
unsigned char brevision;
unsigned int ipageNumber;
unsigned int ireserve1;
unsigned int ireserve2;
unsigned int ireserve3;
unsigned short scrc16;
} DATABASEPAGEHEADER_TypeDef;
我还有以下字节缓冲区存储数组。
char msg_response[]={0x9A,0x17,0x00,0x00,0x17,0x00,0x00,0x00,0x04,0x02,0x9F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xEA,0x4A,0x86};
使用memcpy,我希望将缓冲区映射到结构中。
DATABASEPAGEHEADER_TypeDef * varPageHeader;
varPageHeader=(DATABASEPAGEHEADER_TypeDef*)malloc(sizeof(DATABASEPAGEHEADER_TypeDef));
memcpy(varPageHeader,msg_response,sizeof(DATABASEPAGEHEADER_TypeDef));
然而,结果搞砸了。这是我使用gdb进行的检查(探索结构)。事情很好,直到ipageNumber,我预计它的值为0x0000009f。后来在ireserveX(x = 1,2,3)中。
ibaseRecord = 0x179a .. (Value of type 'unsigned int')
irecordNumber = 0x17 .. (Value of type 'unsigned int')
brecordType = 0x4 .. (Value of type 'unsigned char')
brevision = 0x2 .. (Value of type 'unsigned char')
ipageNumber = 0x0 .. (Value of type 'unsigned int')
ireserve1 = 0x0 .. (Value of type 'unsigned int')
ireserve2 = 0x0 .. (Value of type 'unsigned int')
ireserve3 = 0xea230000 .. (Value of type 'unsigned int')
scrc16 = 0x864a .. (Value of type 'short unsigned int')
(gdb) print sizeof(unsigned int)
$7 = 0x4
有人有解决方案吗?
问题解决了。这是结构对齐问题。谢谢你的帮助。
答案 0 :(得分:4)
结构成员正在与其大小的单元对齐。因此结构在unsigned char brevision
和unsigned int iPageNumber
之间有2个字节的间隔,因此iPageNumber
从4字节边界开始。我不知道符合标准的方法来删除填充,但对于GCC,您可以指定__attribute__((packed))
:
typedef struct __attribute__((packed)) {
unsigned int ibaseRecord;
unsigned int irecordNumber;
unsigned char brecordType;
unsigned char brevision;
unsigned int ipageNumber;
unsigned int ireserve1;
unsigned int ireserve2;
unsigned int ireserve3;
unsigned short scrc16;
} DATABASEPAGEHEADER_TypeDef;
如果你想让它适合携带;不要使用该属性或memcpy。相反,从字节数据中单独初始化结构字段,并考虑使用特定大小的数据类型,如uint32_t
而不是unsigned int
。
答案 1 :(得分:4)
这里有很多错误
1)结构可以包括@Boann指出的包装。
2)字节字节顺序。处理原始字节数据时,您应该知道它的字节序。
在小端模式下,值为0xABCDEF00
的单词将存储为4字节(0x00, 0xEF, 0xCD, 0xAB)
的序列,而在大端模式下则存储为(0xAB, 0xCD, 0xEF, 0x00)
。
由于1)导致的错误是不可预测的。但是,您可以修复由2)引起的错误,这可以通过第一个和第二个无符号整数中的交换字节来观察。 (查看您发送的值的模式和gdb显示的值,然后查看上面的小端和大端的相同值的表示。)