结构和指针

时间:2013-01-31 10:25:54

标签: c pointers structure

我在将条目内存地址获取到结构的成员变量时遇到问题。我试过两种方式,其中一种方法不能正常工作。如果你们给我一些建议,那将是非常好的。

首先,我定义了一个名为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

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

2 个答案:

答案 0 :(得分:2)

你在这里遇到了结构填充。编译器在bfTypebfSize字段之间插入两个字节的填充,以使bfSize与4个字节的大小对齐,因为bfSize是一个DWORD。

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

另请参阅:http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding

答案 1 :(得分: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);

P.S。为了使这个代码可移植, WORD 和endianness的大小必须考虑,很少 #ifdef .. #else .. #endif 应该有帮助。

P.P.S更好的是使用手动逻辑运算和移位运算符而不是转换,但为了简洁起见,将其保留为这种方式。