1

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

我用于查找结构绝对地址的代码是:((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;
}

编辑:好像我在这里找到了堆栈溢出的答案:

如何从其成员的地址获取结构的起始地址

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

4

2 回答 2

0

您对布局(和大小)的唯一保证

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

是成员的地址(分别是包含位字段的单元)按其列表的顺序增加,成员根据它们的类型适当地对齐,并且在 的开头没有填充struct,所以指向的指针适当转换的结构产生指向其第一个成员的指针。编译器可以自由地在成员之间插入比对齐所需更多的填充。

但是,通常,插入的填充只是对齐所需的。size_t并且在大多数实现中,大小和对齐要求struct block*是相同的,在 32 位系统上为 4 个字节,在 64 位系统上为 8 个字节。那么 的大小struct block是 的倍数k = sizeof(size_t),第一个k字节被size成员占用,接下来的k字节被next指针占用。

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

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

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

你很有可能带来实现

offsetof(struct block, data) == sizeof(struct block)

通过在和CHAR_BIT * sizeof(size_t) - 1之间插入一个适当宽度 ( )的未命名位域,但唯一可移植并保证工作的方法是freedata

struct block *b_addr = (struct block*)((char*)(avail->data) - offsetof(struct block, data));

正如Greg Hewgill对相关问题的回答所述。

于 2012-07-02T18:03:54.597 回答
-1

sizeof(struct block) - sizeof(char*)应该给你的大小struct block,不包括data字段。所以,如果你有一个指向 的指针data,你应该到达结构的开头。

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

不过,我还没有测试过。

于 2012-07-02T09:54:54.410 回答