【tuple结构代码】

((type*)0)->field_html

 

 

((type*)0)->field_#include_02

 

计算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