&((myStruct *)0)->x returns 成员 x 在 myStruct 类型中的偏移量如何计算?

How does &((myStruct *)0)->x returns the offset of member x in type myStruct?

typedef struct {
    unsigned char y;
    unsigned short int x;
} myStruct;

void main(void) {
    unsigned char offset = &((myStruct *)0)->x;
    printf("Offset=%d\n", offset);
}

使用这个神奇的宏表达式 &((myStruct*)0)->x returns 成员 xmyStruct 中的偏移量!谁能帮我理解它是如何分配内存的?我 google 我发现创建了一个 myStruct 类型的指针并保存地址 0 然后它计算了成员 x 的地址,这将导致偏移值。我不明白指针如何指向地址 0 ?编译器是如何做到的?地址 0 是在 运行 时间(在主堆栈函数中)加载的虚拟地址吗?提前致谢!

Can anyone help me understand how it is allocated memory?

未分配。没有占用内存,也没有指针在此处取消引用。

编译器只是计算成员x的地址并将其转换为整数。

Unsigned char 不是一种很好的存储偏移量的类型。 C 对此有特殊的类型。它被称为ptrdiff_t。 我宁愿

ptrdiff_t offset = (char *)&(((myStruct *)0)->x) - (char *)&((myStruct *)0);

#define MYOFFSET(st,n) ((char *)&(((st *)0)->x) - (char *)&((st *)0))

ptrdiff_t offset = MYOFFSET(myStruct, x);

在这种情况下没有分配内存,它只是一个虚构的构造。

当你说

   (myStruct*)0

这会创建一个指向恰好位于零的对象的指针,顺便说一句,这并没有错,因为在许多体系结构中,零地址是 100% 有效的,并且通常是控制结构的所在地。

在 x86 上,“零页”描述如下:

https://www.kernel.org/doc/html/latest/x86/zero-page.html

所以“零地址”正好指向“文本模式或帧缓冲区信息(结构screen_info)”,可以在这里看到:

https://docs.huihoo.com/doxygen/linux/kernel/3.7/uapi_2linux_2screen__info_8h_source.html

言归正传,->x 表示成员的位置,然后是 &,它采用该给定成员的地址,该地址应该恰好位于 [=13] =].

由于AddressOfObject为零,则表达式正好等于成员的偏移量。