container_of宏

来源:互联网 发布:淘宝买家账号出错 编辑:程序博客网 时间:2024/05/16 05:22

container_of宏

1. 介绍

  1. 接口:container_of(ptr, type, member)
    • ptr 表示结构体中的member的地址
    • type 结构体类型
    • member 结构体的某个成员
  2. 作用:从包含在某个结构体中的结构成员获取结构体本身的指针,也就是通过结构体变量中的某个成员的首地址获取结构体的首地址

2. 分析

a、原型

  • container_of
#define container_of(ptr, type, member) ({   \const typeof(((type *)0)->member) * __mptr = (ptr); \(type *)((char *)__mptr - offsetof(type, member)); })#endif#ifndef container_of
  • offsetof
#ifndef offsetof#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)#endif

b、分析

第一步:首先定义一个临时的数据类型与ptr相同的变量_mptr,用来保存ptr的值。

  • typeof(((type *)0)->member)用来获取变量的类型

第二步:使用(char *)_mptr的值减去member在结构体偏移量,计算结果就是结构体变量的首地址。

  • 指针的加减要注意类型,用(char*)ptr是为了计算字节偏移。
  • ((type *)0)->member是一个小技巧。

c、实例:

/* 有结构体定义如下: */typedef struct fuck {    ......:    void member;    ......:}type;/* 有类型如下: */type a;type *point;void *ptr;/* 执行: */ptr = &(a.member);point = list_entry(ptr, type, member);
  1. 先看 &((type )0)->member,把0强制转换为指针类型,则该指针一定指向”0”(数据段地址)。因为指针是”type “型的,所以可取到以”0”为基地址的一个type型变量member域的地址。那么这个地址也就等于member域到结构体基地址的偏字节数。

  2. 在看 (type ) (char )(ptr) - (unsigned long)(&((type )0)->member),(char )(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type )0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者相减便得出该结构体的地址。转换为(type )类型即可,ok。

参考博客

0 0
原创粉丝点击