#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编程书之一。它似乎是计算结构偏移但我仍然不知道如何。请帮我详细了解程序。
答案 0 :(得分:3)
代码&((struct name *)0)->b
确实被称为&#34; offsetof&#34;操作,实际上是well-known C macro。
我们的想法是,如果a
是A
类型的结构,那么&a.b
等于a
的地址加上b
的偏移量a
。由于此处使用NULL而不是a
的地址,因此结果只是b
类型结构中A
的偏移量。
根据维基百科,
这可以通过将空指针转换为指向结构st的指针来实现, 然后获得所述结构内的成员m的地址。 虽然这种实现在许多编译器中都能正常工作,但它具有 根据C标准2的未定义行为,因为它涉及到 取消引用空指针(尽管如此,有人可能会认为没有 取消引用发生,因为计算整个表达式 在编译时)
让我们一步一步地看printf
中的表达式。
如上所述,表达式(unsigned int) & ( (struct name *)0 )->b))
计算b
中struct 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");
的值,然后打印出来。