我在将条目内存地址获取到结构的成员变量时遇到问题。我试过两种方式,其中一种方法不能正常工作。如果你们给我一些建议,那将是非常好的。
首先,我定义了一个名为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
为什么第一种方法不起作用?我认为这两种方法完全相同。
答案 0 :(得分:2)
你在这里遇到了结构填充。编译器在bfType
和bfSize
字段之间插入两个字节的填充,以使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更好的是使用手动逻辑运算和移位运算符而不是转换,但为了简洁起见,将其保留为这种方式。