请参阅我以下使用的结构。我希望以便携的方式解决这个问题。
我用于查找结构的绝对地址的代码是:(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
它给了我正确的绝对地址。
答案 0 :(得分: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}}指针。
之后是宽度为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);
我还没有测试过它。