给定结构中灵活数组成员的绝对地址,如何获取结构的绝对地址?

时间:2012-07-02 09:34:00

标签: c

请参阅我以下使用的结构。我希望以便携的方式解决这个问题。

我用于查找结构的绝对地址的代码是:(char*)data - sizeof(struct block);(其中data是结构块中数据的地址)。它不适用于这个结构。

我在最后一个断言失败的地方看到了一个测试程序。

如果我将unsigned int free:1;更改为unsigned int free;,则两张照片都会打印12张,因此sizeof会给我预期的结果。

提前致谢。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct block {
        size_t          size;
        struct block*   next;
        unsigned int    free:1;
        char            data[];
};

int main(void)
{
        struct block*   avail;
        struct block*   b;

        avail = malloc(sizeof(struct block) + 10);

        printf("%zu \n", sizeof(struct block)); // prints 12

        printf("%zu\n", avail->data - (char*)&avail->size); //prints 9

        b = (struct block*)((char*)avail->data - 9);
        assert(b == avail);

        b = (struct block*)((char*)avail->data - sizeof(struct block));
        assert(b == avail);

        return 0;
}
编辑:好像我在堆栈溢出时找到了答案:

how to get struct's start address from its member's address

它给了我正确的绝对地址。

2 个答案:

答案 0 :(得分:0)

您对

的布局(和尺寸)的唯一保证
struct block {
        size_t          size;
        struct block*   next;
        unsigned int    free:1;
        char            data[];
};

是成员的地址(或者单位包含位字段)按照列表的顺序增加,成员适合于他们的类型,并且在开始时没有填充struct,所以指向结构的指针,适当地转换产生指向其第一个成员的指针。编译器可以在成员之间插入比对齐所需的更多填充。

然而,通常,插入的填充仅是对齐所需的。此外,size_tstruct block*的大小和对齐要求在大多数实现中都是相同的,32位系统上的4个字节和64位系统上的8个字节。然后struct block的大小是k = sizeof(size_t)的倍数,k成员占用第一size个字节,k成员占用下一个next个字节{1}}指针。

之后是宽度为1的无符号位域。这样一个小的位域适合任何存储单元,因此实现可以自由选择任何大小的存储单元。自然选择将是

  • 一个字节,因为它是可能的最小单位,
  • sizeof(int)个字节,因为&#34;一个''plain''int对象具有执行环境架构所建议的自然大小&#34;。

现在,如果选择包含位字段的单位具有一个字节的大小,就像您的实现(和我的)一样,data成员通常直接放在那之后,在2*k+1字节的偏移处,因为char的对齐是1.如果位字段的单位选择为int - 大小,则{{1}的偏移量很可能是data,在32位系统上可能等于2*k + sizeof(int),但不在64位系统上。

你可以非常高的概率带来实现

sizeof(struct block)

offsetof(struct block, data) == sizeof(struct block) CHAR_BIT * sizeof(size_t) - 1之间插入一个适当宽度(free)的未命名位域,但唯一可移植且保证可行的方式是

data

Greg Hewgill's answer所述,链接问题。

答案 1 :(得分:-1)

sizeof(struct block) - sizeof(char*)应该为您提供struct block的大小,不包括data字段。因此,如果您有指向data的指针,则应该到达结构的开头。

b = (struct block*)((char*)avail->data - (sizeof(struct block) - sizeof(char*));
assert(b == avail);

我还没有测试过它。