printf(“%d\n”,FPOS(person,name));
}
^_^[sunny@localhost ~]52$ ./a.out
20
#define
OFFSETOF(type, field) ((size_t)&(((type
*)0)->field))
(type
*)0:把0地址当成type类型的指针。
((type
*)0)->field:对应域的变量。
&((type
*)0)->field:取该变量的地址,其实就等于该域相对于0地址的偏移量。
(size_t)&(((type
*)0)->field):将该地址(偏移量)转化为size_t型数据。
ANSI
C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指
针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构
体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常
量)地址,这样就完全避免了通过NULL指针访问内存的问题。
有人这样表达:
#define
OFFSETOF(type, field) ((size_t) \
((char *)&((type *)0)->field – (char *)(type</