memcpy复制错误的字节数

时间:2013-12-29 00:45:29

标签: c memcpy

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

有人有解决方案吗?

问题解决了。这是结构对齐问题。谢谢你的帮助。

2 个答案:

答案 0 :(得分:4)

结构成员正在与其大小的单元对齐。因此结构在unsigned char brevisionunsigned 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显示的值,然后查看上面的小端和大端的相同值的表示。)