#define Offset(type,field) ((size_t)&((type *)0->field))
对0取指针的操作((type *)0)的结果就是一个类型为type *的NULL指针。如果利用这个NULL指针访问type成员,当然是非法的,但是因为&((type *)0->field)的意图只不过是计算field字段的地址,因此是合法的。
编译器根本就不生成访问type的代码,而仅仅是根据type的内容布局和结构体实例首址在编译期计算这个(常量)的地址,这样就完全避免了通过NULL指针访问内存可能出现的问题。同时又因为地址为0,所以这个地址的值就是字段相对于结构体基址的偏移。
#include<stdio.h>
#define OffSet(type,field) ((size_t)&(((type*)0)->field))
typedef struct MyStr
{
char a;