• 关于宏:container_of和 offsetof以及list_for_each_entry


    1.offsetof(TYPE, MEMBER)

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

    offsetof是一个自定义的宏,其返回值是一个member成员在一个type类型的结构体中相对于结构体首地址的字节偏移量;

    分析其工作原理:
    1.(TYPE *)0将0地址强制转换成TYPE *类型指针---------且可以认为,这个类型的结构体的首地址是0x0;
    2.(TYPE *)0->MEMBER以指针形式访问成员MEMBER;
    3.&((TYPE *)0->MEMBER)取成员MEMBER的地址;
    因为是从0地址开始的,所以取得成员变量MEMBER的地址等于=相对与结构体首地址的偏移地址;
    4.((size_t) &((TYPE *)0)->MEMBER),然后将强制类型转换成int型,作为offsetof的返回值;

    2.container_of

    #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) * __mptr = (ptr);(type *)( (char *)__mptr - offsetof(type,member) );})

    作用:根据一个结构体变量中的一个域成员变量的指针(也就是地址)来获取指向整个结构体变量的指针(地址)的功能
    分析:
    1).const typeof( ((type *)0)->member ) * __mptr = (ptr)
      typeof( ((type *)0)->member )这里获得member成员的类型
      typeof()就是由变量名得到变量数据类型的;
    2).const typeof( ((type *)0)->member ) * __mptr = (ptr)

      定义一个const typeof() * __mptr类型的指针,并初始化为ptr;这里的ptr是一个指向type类型结构体成员变量member的指针,也就是member在结构体中的地址;
    3).(char *)__mptr

      这里将__mptr指针强制类型转换成char *类型:
      原因是: 如果_mptr为int *类型, _mptr - offset 相当于减去 sizeof(int)*offset个字节;
    4).offsetof(type,member)

      就是一个得到member相当于结构体首地址的偏移量,以字节单位;
    5).(char *)__mptr - offsetof(type,member)
      得到_mptr所在结构体的首地址;
    6).(type *)( (char *)__mptr - offsetof(type,member))
      将得到的结构体首地址强制类型转换成type *类型;

    3.list_for_each_entry

    #define list_for_each_entry(pos, head, member)                
        for (pos = list_entry((head)->next, typeof(*pos), member);    
             prefetch(pos->member.next), &pos->member != (head);     
             pos = list_entry(pos->member.next, typeof(*pos), member))

    在这里,list_for_each_entry就是一个for循环:

    for ( pos = list_entry((head)->next, typeof(*pos), member); prefetch(pos->member.next), &pos->member != (head); pos = list_entry(pos->member.next, typeof(*pos), member))
    1) pos = list_entry((head)->next, typeof(*pos), member)

      其中:

      #define list_entry(ptr, type, member) container_of(ptr, type, member)  

      因此:

      pos = list_entry((head)->next, typeof(*pos), member)
      等价于:
      pos = container_of((head)->next, typeof(*pos), member)

      所以:pos被初始化为一个指向 结构体成员变量member所在的结构体(结构体类型为typeof(*pos))  的指针;

      由于container_of的第一个参数是head->next,所以被初始化的pos是指向头结点的下一个节点;

     2)  prefetch(pos->member.next), &pos->member != (head)

      判断是否又到达头结点,表明遍历结束

     3)  pos = list_entry(pos->member.next, typeof(*pos), member)

       是pos指向下一个链表节点;

  • 相关阅读:
    微软发布3款SQL Injection(SQL 注入)攻击检测工具
    TortoiseSVN 使用介绍
    windows下的Bug跟踪管理软件Bugfree的安装
    国内PHP开源建站程序一览
    55个经典开源Windows工具
    JavaScript代码格式化工具(JS代码分析必备)
    Javascript工具 使用packer来压缩JS文件
    开源UML设计工具StarUML
    看似简单的问题其实不简单
    Javascript工具 使用JSDoc建立JavaScript代码的文档
  • 原文地址:https://www.cnblogs.com/weiyouqing/p/9031471.html
Copyright © 2020-2023  润新知