本文讲解typeof( ((type *)0)->member )的含义,并在此基础上学习offset_of()的用法。
typeof( ((type *)0)->member )
ANSI C标准允许值为0的常量被强制转换成任何一种类型的指针,并且转换的结果是个NULL,因此((type *)0)的结果就是一个类型为type *的NULL指针.
如果利用这个NULL指针来访问type的成员当然是非法的,但typeof( ((type *)0)->member )是想取该成员的类型(有关typeof()的用法可参考这里),所以编译器不会生成访问type成员的代码。类似的代码&( ((type *)0)->member )在最前面有个取地址符&,它的意图是想取member的地址,所以编译器同样会优化为直接取地址。
struct apple{
int weight;
int color;
};
int main(int argc, char *argv[])
{
int weight = 5;
typeof(((struct apple *)0)->weight) *ap1 = &weight;//定义一个指针变量ap1, ap1的类型为apple成员weight的类型。
printf("ap1's value:%d\n", *ap1);
}
printf("%d\n", offset_of(struct apple, color));
[root@xxx c_base]# ./a.out
ap1's value:5
offset_of()
理解了以上内容后再看offset_of(),它的作用是获取结构体中某个成员相对于该结构体首元素地址的偏移量。
#define offset_of(type, memb) \
((unsigned long)(&((type *)0)->memb))
比如想知道sruct apple中的color是在结构体中的哪个位置,可以这么做:
printf("colore offset addr:%d\n", offset_of(struct apple, color));
[root@xxx c_base]# ./a.out
colore offset addr:4
如上结果表示colore成员在结构体apple中的偏移地址是4.