有个宏定义如下:
#define FIELD_OFFSET(type, field)    ((LONG)(INT_PTR)&(((type *)0)->field))
我左看右看,看不懂,这个宏究竟干嘛用的.请大侠指点指点.
这个宏的含义是不是先把 0转换为(type*) 类型,然后取域 field ,对NULL指针进行操作不会引起异常么?

解决方案 »

  1.   

    这个宏的意思是取出结构体中指定成员相对于结构体起始地址的偏移
    因为是宏替换,由编译器计算偏移,所以不会生成访问0(NULL)地址的指令,不引起异常
    假设有
    struct {
      BYTE a;
      BYTE b;
      BYTE c;
    }demo_t;
    计算LONG offset = FIELD_OFFSET(demo_t, c)替换之后就变为
    offset = ((LONG)(INT_PTR)&(((demo_t*)0)->c));
    编译器再次展开时首先计算c相对于(demo_t*)的偏移为2(编译器肯定知道),然后&操作符取相对于0的地址也等于2,最后再转换成LONG,结果就得2,刚好是c的偏移
      

  2.   

    以0为基地址寻址后以转为LONG
      

  3.   

    哦,这个宏是取地址,然后把地址转换为LONG,所以不会引起非法操作.我这个理解对么?
    但是我对下面的运行结果感觉很疑惑typedef struct {    BYTE           a;
        REFERENCE_TIME  b;
        BYTE            c[1];
        
    }demo_t;
         
     TRACE("FIELD_OFFSET(demo_t,a) %d \n", FIELD_OFFSET(demo_t,a));
     TRACE("FIELD_OFFSET(demo_t,b) %d\n", FIELD_OFFSET(demo_t,b));
     TRACE("FIELD_OFFSET(demo_t,c) %d\n", FIELD_OFFSET(demo_t,c));
     TRACE("FIELD_OFFSET(demo_t,c[10]) %d\n", FIELD_OFFSET(demo_t,c[10]));
     

    TRACE("FIELD_OFFSET(AM_SAMPLE2_PROPERTIES,dwTypeSpecificFlags) %d \n", FIELD_OFFSET(AM_SAMPLE2_PROPERTIES,dwTypeSpecificFlags));运行的结果是FIELD_OFFSET(demo_t,a) 0 
    FIELD_OFFSET(demo_t,b) 8
    FIELD_OFFSET(demo_t,c) 16
    FIELD_OFFSET(demo_t,c[10]) 26FIELD_OFFSET(AM_SAMPLE2_PROPERTIES,dwTypeSpecificFlags) 4 ??????这个值为什么是4 而不是8呢?typedef struct tagAM_SAMPLE2_PROPERTIES {
        DWORD           cbData;
        DWORD           dwTypeSpecificFlags;
        DWORD           dwSampleFlags;
        LONG            lActual;
        REFERENCE_TIME  tStart;
        REFERENCE_TIME  tStop;
        DWORD           dwStreamId;
        AM_MEDIA_TYPE   *pMediaType;
        BYTE            *pbBuffer;
        LONG            cbBuffer;
    } AM_SAMPLE2_PROPERTIES;
      

  4.   

    我是这么想的: 对于demo_t 来说b的长度是8,a要和它对齐,c[10]相对c[0]偏移了10个byte,所以是b的地址是8,c[10]的地质是26。具体的规则我也说不上,我想这肯定和VC编译器有关
      

  5.   

    通过实验,我觉得vc对结构中的长度是这样计算的:以结构中长度最大的元素为界限,前面的所有成员的长度必须是它的整数倍,如果不够则添足,后面也同样处理,比如说
    typedef struct {    BYTE           a;
        REFERENCE_TIME b;
        BYTE            c[1];
         BYTE            cc;
          BYTE            ccc;
         BYTE            cccc;
        //BYTE            ccccc;
         DWORD            d;
    }demo_t;
    的长度便是 24 但是对于结构
    typedef struct {    BYTE           a;
        REFERENCE_TIME b;
        BYTE            c[1];
         BYTE            cc;
          BYTE            ccc;
         BYTE            cccc;
          BYTE            ccccc;
         DWORD            d;
    }demo_t;
    他的长度便是32。大伙可以生成一个对象,给它负值,然后在memory 窗口里看这个变量的
    结构就可以一目了然了