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

时间:2016-01-05 18:56:51

标签: c pointers casting printf offset

#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编程书之一。它似乎是计算结构偏移但我仍然不知道如何。请帮我详细了解程序。

1 个答案:

答案 0 :(得分:3)

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

我们的想法是,如果aA类型的结构,那么&a.b等于a的地址加上b的偏移量a。由于此处使用NULL而不是a的地址,因此结果只是b类型结构中A的偏移量。

根据维基百科,

  

这可以通过将空指针转换为指向结构st的指针来实现,   然后获得所述结构内的成员m的地址。   虽然这种实现在许多编译器中都能正常工作,但它具有   根据C标准2的未定义行为,因为它涉及到   取消引用空指针(尽管如此,有人可能会认为没有   取消引用发生,因为计算整个表达式   在编译时)

让我们一步一步地看printf中的表达式。

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

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

总和产生内存地址。该地址等于对象na中成员变量char *的地址,并且类型为int *。知道了,最后一步是将地址转回b(因为int的类型是b),然后取消引用结果(再一次,我们知道它指向到b)。最终结果是$('#cars').on('change', function(e) { var valueSelected = this.value; console.log(valueSelected); }); $("#cars").val("Toyota"); $("#cars").trigger("change");的值,然后打印出来。