1

我在将入口内存地址获取到结构的成员变量时遇到问题。我尝试了两种方法,其中一种不能正常工作。如果大家给我一些建议,那就太好了。

首先,我定义了一个名为 BITMAP_HEADER 的结构。

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

其次,我定义并初始化了一些变量。请在阅读下一行之前查看下面的代码。如果你问我为什么有一个字符指针,我需要访问整数 bfSize 的每个字节。

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

第三,我以两种不同的方式获得了 bfSize 的内存地址并打印了这些值

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

(1) 直接拿到bitmap_header.bfSize的内存地址。

(2) 获得结构 BITMAP_HEADER 的内存地址,并将指向下一个的指针移动 2 个字节。

最后,这是结果。

2D
F6

供您参考,这里是结构 BITMAP_HEADER 的十六进制数据。

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

为什么第一种方法不起作用?我认为这两种方法完全相同。

4

2 回答 2

2

您在这里遇到了结构填充。bfType编译器在and字段之间插入两个字节的填充bfSize,以对齐bfSize4 个字节的大小,因为bfSize它是一个 DWORD。

一般来说,您不能依赖能够计算结构内的精确偏移量,因为编译器可能会在成员之间添加填充。您可以使用特定于编译器的位在某种程度上控制它;例如,在 MSVC 上,pack pragma,但我不建议这样做。结构填充用于指定成员对齐限制,并且某些架构会在未对齐访问时出错。(其他人可能会手动修复对齐,但通常这样做会相当缓慢。)

另见:http ://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding

于 2013-01-31T10:28:29.293 回答
0

对于预先知道结构的原始数据,通常最好将其读取到数组中并使用定义的偏移量来访问所需的字段。这样您就不必担心编译器的行为(这通常可能与您的预期不同)。您的代码如下所示:

#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);

PS 为了使此代码可移植,必须考虑WORD的大小和字节序,少数#ifdef.. #else.. #endif应该对此有所帮助。

PPS 最好使用手动逻辑运算和移位运算符而不是强制转换,但为了简洁起见,将其保留为这种方式。

于 2013-01-31T11:09:55.503 回答