Structure and pointer

自古美人都是妖i 提交于 2019-12-24 07:58:05

问题


I'm having a problem getting the entry memory address to a member variable of a structure. I've tried in two ways, one of which didn't work properly. It would be very good if you guys give me some advice.

First, i defined a structure named BITMAP_HEADER.

struct BITMAP_HEADER
{
    WORD    bfType ;
    DWORD   bfSize ; 
    WORD    bfReserved1 ;
    WORD    bfReserved2 ;
    DWORD   bfOffBits ;
} ;

Second, i defined and initialized some variables. please look at the code below before you read next line. In case you ask me why i got a character pointer, i needed to access each bytes of integer bfSize.

struct BITMAP_HEADER    bitmap_header ;
char*                   pSize = (char*)&bitmap_header.bfSize;

Third, i got a memory address to the bfSize in two different ways and printed the values.

1. printf("%X\n", *pSize) ;
2. printf("%X\n", (unsigned char)*(((char*)&bitmap_header)+2)) ; 

(1) directly got a memory address to the bitmap_header.bfSize.

(2) got a memory address to the structure BITMAP_HEADER and shifted the pointer to the next by 2 bytes.

Finally, here is the result.

2D
F6

For your information, here is the hex data of the structure BITMAP_HEADER.

42 4D / F6 C6 2D 00 / 00 00 / 00 00 / 36 00 00 00

Why didn't the first method work? I thought the two methods were exactly same.


回答1:


You're running into structure padding here. The compiler is inserting two bytes' worth of padding between the bfType and bfSize fields, to align bfSize to 4 bytes' size, since bfSize is a DWORD.

Generally speaking, you cannot rely on being able to calculate exact offsets within a structure, since the compiler might add padding between members. You can control this to some degree using compiler-specific bits; for example, on MSVC, the pack pragma, but I would not recommend this. Structure padding is there to specify member alignment restrictions, and some architectures will fault on unaligned accesses. (Others might fixup the alignment manually, but typically do this rather slowly.)

See also: http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding




回答2:


As for the raw data which structure is known in advance, it usually better to read it to an array and use defined offsets to access required fields. This way you won't have to worry about compiler's behaviour (which might often be not as you expected). Your code would look like:

#define FIELD_TYPE  0
#define FIELD_SIZE  2
#define FIELD_RES1  6
#define FIELD_RES2  8
#define FIELD_OFF   10
#define SIZE_HEADER 14

static uint8_t header[SIZE_HEADER];

<...>
uint8_t * pheader = header;
DWORD offset_bits = (DWORD)*(pheader + FIELD_OFF);

P.S. to make this code portable, size of WORD and endianness must be considered, few #ifdef.. #else.. #endif should help with that.

P.P.S it would be even better use manual logical operations and shift operators instead of casting, but left it this way for the sake of brevity.



来源:https://stackoverflow.com/questions/14623502/structure-and-pointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!