【问题标题】:Structure and pointer结构和指针
【发布时间】:2013-01-31 10:25:53
【问题描述】:

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

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

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

【问题讨论】:

    标签: c pointers structure


    【解决方案1】:

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

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

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

    【讨论】:

    • 你们到底有什么不知道的?太棒了..谢谢你的帮助。它帮助很大。
    • @bis0317:点击“接受答案”,这就是我所需要的。另外,关于学习这些东西:嗯,我从 12 岁就开始这样做了。在此过程中,我了解到什么是结构填充。 (没有什么比经验更重要了。)
    • 你的意思是格子按钮吗?我刚点了!谢谢!
    • 我猜x86(32bit)cpu读取内存4字节,这就是你提到的数据对齐存在的原因。我想知道x64 cpu会发生什么。他们是否按 8 个字节读取内存?原谅我打扰你了。
    【解决方案2】:

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

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

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

    P.P.S 最好使用手动逻辑运算和移位运算符而不是强制转换,但为了简洁起见,就这样保留了。

    【讨论】:

    • 哇!这是一件很了不起的事情。你真是个天才!!谢谢!!
    • 不,实际上远非如此。我刚刚在嵌入式世界中长大,这是一种常见的做法..
    • 这对我来说是全新的......!谢谢你让我知道。哈哈!!
    猜你喜欢
    • 2020-04-15
    • 2015-07-10
    • 2013-02-15
    • 2023-04-04
    • 2016-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多