如何计算结构的偏移量?在这里解释一下 printf 语句?

How offset of structure is calculated? Explain printf statement here?

#include<stdio.h>
main()
{
        unsigned char c;
        typedef struct name {
                long  a;
                int b;
                long c;
        }r;
        r re = {3,4,5};
        r *na = &re;
        printf("%d", *(int*) ((char*)na + (unsigned int) & ( (struct name *)0 )->b));
}

输出:

4

如果有人能详细解释一下 printf 语句在这个 c 程序中的作用,我将不胜感激?据我说 int 是铸造的。然后 char 指针被转换为 na。但我不明白整个陈述总体上在做什么?在这里做什么铸造? b 不是指针,但它似乎被用作指针。我发现这个问题之一是 c 编程 book.It 似乎是计算结构偏移量,但我仍然不知道如何计算。请帮助我详细了解程序。

代码 &((struct name *)0)->b 确实被称为 "offsetof" 操作,实际上是 well-known C macro.

思路是,如果aA类型的结构,那么&a.b等于a的地址加上[=15=的偏移量] 在 a。由于这里使用 NULL 代替 a 的地址,结果只是 b 在类型 A 的结构中的偏移量。

根据维基百科,

This works by casting a null pointer into a pointer to structure st, and then obtaining the address of member m within said structure. While this implementation works correctly in many compilers, it has undefined behavior according to the C standard,2 since it involves a dereference of a null pointer (although, one might argue that no dereferencing takes place, because the whole expression is calculated at compile time)

所以让我们看一下printf step-by-step.

中的表达式

表达式(unsigned int) & ( (struct name *)0 )->b))如上所述计算bstruct name中的偏移量并将结果转换为整数。在大多数平台上,结果应等于 sizeof(long)

代码中的(char*)nana强制转换为struct name的指针为char指针。这是必需的,因为 sizeof(char) 可以假定为 1,而 sizeof(*na) 大于 1。我们要做的是使用 *na 的地址作为原始数字地址,而不是做pointer arithmetic,因此如果例如 na==0x1234,则 ((char*)na + 4) 的结果等于 0x1234 + 4 = 0x1238

求和得到一个内存地址。该地址等于对象na中成员变量b的地址,类型为char *。知道了,最后一步是将地址转换回 int *(因为 b 的类型是 int)然后取消引用结果(再一次,我们知道它指向b)。最后的结果是 b 的值,然后打印出来。