((type*)0)->field
【tuple结构代码】
计算t_bits offset看上去应该是32,结果是23
【相关逻辑】
1) (type*)0
一个 type 类型的NULL指针
用这个指针访问结构体内的成员是非法的
2)&(((type*)0)->field)
计算 field 的地址 ,编译器不会产生访问 field 的代码,只会根据 type 的布局和起始地址在编译期计算这个地址(常量)。而又因为初始地址为 0,故该地址的值就是该结构体成员相对于结构体基址的偏移
3)sizeof(union),结果是 union 占用内存最大成员的大小(各成员共享内存)
typedef unsigned char uint8; /* == 8 bits */ typedef unsigned short uint16; /* == 16 bits */ typedef unsigned int uint32; /* == 32 bits */ typedef uint8 bits8; #include <cstdio> #define offsetof(type, field) ((long) &((type *)0)->field) typedef struct BlockIdData { uint16 bi_hi; uint16 bi_lo; } BlockIdData; typedef uint16 OffsetNumber; typedef struct ItemPointerData { BlockIdData ip_blkid; OffsetNumber ip_posid; }; typedef uint32 TransactionId; typedef signed int int32; typedef struct DatumTupleFields { int32 datum_len_; /* varlena header (do not touch directly!) */ int32 datum_typmod; /* -1, or identifier of a record type */ unsigned int datum_typeid; /* composite type OID, or RECORDOID */ } DatumTupleFields; typedef struct HeapTupleFields { TransactionId t_xmin; /* inserting xact ID */ TransactionId t_xmax; /* deleting or locking xact ID */ union { uint32 t_cid; /* inserting or deleting command ID, or both */ TransactionId t_xvac; /* old-style VACUUM FULL xact ID */ } t_field3; } HeapTupleFields; struct HeapTupleHeaderData { union { HeapTupleFields t_heap; // 12 DatumTupleFields t_datum; // 12 } t_choice; ItemPointerData t_ctid; // 6 uint16 t_infomask2; // 2 uint16 t_infomask; // 2 uint8 t_hoff; // 1 bits8 t_bits[4]; }; int main(){ printf("c=%d",offsetof(HeapTupleHeaderData,t_bits)); }
参考
http://www.myexceptions.net/program/1988566.html