• 认真理解 offsetof宏定义


    我们经常遇到一种场景,比如把 链表结点或者队列结点 放入到 数据结构体 中,当我们知道结点地址,想要得到数据结构的地址,下面这个宏可以出场了。

    #define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER ) 

    举例: 

    #include<stdio.h> 
    typedef struct _test 
    { 
      char i; 
      int j; 
      char k; 
    }Test; 
    int main() 
    { 
      Test *p = 0; 
      printf("%p ", &(p->k)); 
    } 

    大概可以总结为以下4步: 

    1. ( (TYPE *)0 ) 将零转型为TYPE类型指针; 
    2. ((TYPE *)0)->MEMBER 访问结构中的数据成员; 
    3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址; 
    4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型.巧妙之处在于将0转换成(TYPE*),结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址; 

    结果很好,但是自己有两个疑问:

    1.结构体中,成员变量表示的地址在内存中是怎样分布得,会以什么结果显示?

    2.强转0指针,上面只做第二步操作会不会挂掉?

    举例:

    struct item_s{
    
      void *data;
    
      struct item_s *next;
    
    };
    
    int main(int argc,char **argv){
    
      struct item_s item_ins={0};
    
      struct item_s *itemp_ins=NULL;
    
      1.printf(&item_ins);
    
      2.printf(&(item_ins.is_tmp));
    
      3.printf(itemp_ins->is_tmp);
    
      4.printf("%x\n",&(itemp_ins->is_tmp))
    
    }

    然后疑问解决,通过1 2结果对比,会发现,他们的差值即为 成员地址相对结构体地址 的偏移量。通过3 4结果对比,会发现,在一个地址为0x0上是不能直接做取操作得,但是通过取地址符操作可以取得偏移量。

  • 相关阅读:
    616无趣
    安装elasticsearch的问题
    导出PDF数据
    生活本苦,奈何年华
    分享一个sql查询重复记录
    springboot的java打印票据-4
    springboot的java打印票据-3
    springboot的java打印票据-2
    react 学习笔记
    原生可拖动表格
  • 原文地址:https://www.cnblogs.com/claresun/p/3433742.html
Copyright © 2020-2023  润新知