1.I have the following structure.
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;
I also have following byte buffer storing an array.
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};
Using memcpy, I expect to map the buffer into the structure.
DATABASEPAGEHEADER_TypeDef * varPageHeader;
varPageHeader=(DATABASEPAGEHEADER_TypeDef*)malloc(sizeof(DATABASEPAGEHEADER_TypeDef));
memcpy(varPageHeader,msg_response,sizeof(DATABASEPAGEHEADER_TypeDef));
However, the result messes up. Here is the inspection I made using gdb (explore the struct). Things were fine until the ipageNumber, which I expected to have value 0x0000009f.And also later in 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
Does anyone have solution to it?
problem solved. It was the struct alignment problem. Thank you for your kind help.
The struct members are being aligned to units of their size. So the struct has a 2-byte gap between unsigned char brevision
and unsigned int iPageNumber
, so that iPageNumber
starts at a 4-byte boundary. I'm not aware of a standards-compliant way to remove that padding, but for GCC you can specify __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;
If you want to make this properly portable though; don't use that attribute, or memcpy at all. Instead, initialize your struct fields individually from the byte data, and consider using specifically sized data types like uint32_t
instead of unsigned int
.