这与malloc无关。发生的事情非常简单 - 通过指针 X 引用结构成员只需将偏移量添加到存储在指针 X 中的内存地址(其值)。因此,您只需将偏移量应用于 malloc 返回的指针。
请记住,编译后的二进制文件中不存在结构 - 它只是高级编程语言的编译时“概念”。您甚至可以使用offsetof 宏获取结构中每个成员的偏移量。
因此,从哪里获得指针以及它的值是什么并不重要,您始终可以通过将其偏移量(编译器始终知道)添加到结构的“字段”地址来计算存储在指针中的值。
这里有一个小例子来证明这一点:
#include <stddef.h>
#include <stdio.h>
struct my_struct {
int x;
int y;
};
int main()
{
struct my_struct *s;
/* Print relative offsets of the structure member fields: */
printf("Offset of 'x': %lu\n", offsetof(struct my_struct, x));
printf("Offset of 'y': %lu\n", offsetof(struct my_struct, y));
/*
* Assign some random memory address to a pointer and print addresses
* of the structure and its members. You can see that they are related,
* pointer to 'x' will always be the same as pointer to structure +
* `offsetof(struct my_struct, x)` and pointer to 'y' as pointer to
* structure + `offsetof(struct my_struct, y)`
*/
s = (void *)0xDEADBEEF;
printf("Pointer to structure: %p\n", s);
printf("Pointer to x: %p (x - base = %ld)\n",
&s->x, (ptrdiff_t)&s->x - (ptrdiff_t)s);
printf("Pointer to y: %p (y - base = %ld)\n",
&s->y, (ptrdiff_t)&s->y - (ptrdiff_t)s);
return 0;
}
不同平台上的结果可能不同,这是我在 Intel x86_64 上的结果:
$ clang -Weverything -o test ./test.c && ./test
Offset of 'x': 0
Offset of 'y': 4
Pointer to structure: 0xdeadbeef
Pointer to x: 0xdeadbeef (x - base = 0)
Pointer to y: 0xdeadbef3 (y - base = 4)
请注意,您始终可以在运行时计算和字段偏移量。与offsetof 的主要区别在于它可以用于计算compile-time 中的偏移量。
另外,尝试自己计算字段偏移时要小心。虽然编译器无法重新排列字段,但它可以轻松执行padding and alignment,如果需要,可以在字段成员之间有效地添加隐式“空”空间。
希望对您有所帮助。祝你好运!