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

C 给定结构中灵活数组成员的绝对地址,如何获取结构的绝对地址?,c,C,请看下面我使用的结构。我希望以一种便携的方式解决这个问题 我用于查找结构的绝对地址的代码是:(char*)data-sizeof(struct block)(其中数据是结构块中数据的地址)。它在此结构上不起作用 我做了一个测试程序,最后一次断言失败 如果我更改无符号int-free:1到无符号整数两次打印都将打印12,因此sizeof给出了预期的结果 提前谢谢 #include <stdio.h> #include <stdlib.h> #include <asse

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

我用于查找结构的绝对地址的代码是:
(char*)data-sizeof(struct block)(其中数据是结构块中数据的地址)。它在此结构上不起作用

我做了一个测试程序,最后一次断言失败

如果我更改
无符号int-free:1
无符号整数两次打印都将打印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;
}
#包括
#包括
#包括

它给了我正确的绝对地址

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

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

不过,我还没有对它进行测试。

关于布局(和大小)的唯一保证

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

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

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

  • 一个字节,因为它是最小的单位
  • sizeof(int)
    bytes,因为“普通”int对象具有执行环境架构建议的自然大小”
现在,如果选择包含位字段的单元的大小为一个字节,就像您(和我的实现)的情况一样,
data
成员通常直接放置在该单元之后,偏移量为
2*k+1
字节,因为
char
的对齐为1。如果位字段的单位选择为
int
大小,则
数据的偏移量很可能为
2*k+sizeof(int)
,在32位系统上可能等于
sizeof(struct block)
,但在64位系统上则不相同

你可以很有可能使实现成为现实

offsetof(struct block, data) == sizeof(struct block)
通过在
自由
数据
之间插入适当宽度的未命名位字段(
CHAR\u bit*sizeof(size\u t)-1
),但唯一可移植且保证工作的方法是

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

如链接问题的中所述。

灵活数组成员的可能重复项不是指针,并且不计入结构的基本大小,因此这将产生错误的结果。
struct block *b_addr = (struct block*)((char*)(avail->data) - offsetof(struct block, data));