Вопрос

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.

Другие советы

There are multiple things wrong here

1) struct can include packing as pointed out by @Boann.

2) Byte endianness. When dealing with raw byte data you should be aware of it's endianness. in little endian mode, a word with value 0xABCDEF00 is stored as sequence of 4 bytes (0x00, 0xEF, 0xCD, 0xAB) while in big endian mode is stored as (0xAB, 0xCD, 0xEF, 0x00).

Error due to 1) is unpredictable. However, You can fix error caused by 2) as can be observed by the swapped bytes in the 1st and second unsigned ints. (Look at the pattern of values you sent and the values displayed by gdb and then look at the representation of the same value in little and big endian above).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top