container_of宏
1. 介绍
container_of宏,是linux内核中常用的一个宏。
1. 接口:container_of(ptr, type, member)
- ptr 表示结构体某个成员的地址
- 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)); })
- 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 = container_of(ptr, type, member);
先看 &((type )0)->member,把0强制转换为指针类型,则该指针一定指向”0”(数据段地址)。因为指针是”type “型的,所以可取到以”0”为基地址的一个type型变量member域的地址。那么这个地址也就等于member域到结构体基地址的偏字节数。
在看 (type ) (char )(ptr) - (unsigned long)(&((type )0)->member),(char )(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type )0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者相减便得出该结构体的地址。转换为(type )类型即可,ok。