Container_of
container_of 宏
Linux 内核第一宏。主要作用:
根据结构体某一成员的地址,获取这个结构体的首地址。
主要原理:
用结构体成员的地址,减去该成员在结构体内的偏移,即可得到该结构体的首地址。
1 |
|
container_of 宏三个参数:
- type: 结构体类型
- member: 结构体内的成员
- ptr: 结构体内成员member的地址
container_of 宏实现分析
offsetof 宏
其功能是获得成员MEMBER在TYPE结构中的偏移量
结构体作为一个复合类型数据,里面可包含多个变量。当我们定义一个结构体时,编译器要为其在内
存中分配空间。根据每个成员的数据类型和字节对齐方式,编译器会按照结构体中各个成员的顺序,在
内存中分配一片连续的空间来存储他们。
一个结构体数据类型,在同一编译环境下,各个成员相对于结构体首地址的偏移是固定不变的。
当结构体的首地址为0时,结构体中各个成员的地址在数值上等同于结构体各成员相对于结构体首地址的偏移
1 | struct student { |
因为常量指针的值为0,即可以看作结构体首地址为0,
所以结构体每个成员变量的地址即该成员相对于结构体首地址的偏移。
这正是offsetof
宏的功能。
1 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
根据运算符优先级分析:
(TYPE *)0
: 将0地址强制转化为一个指向TYPE类型的结构体常量指针(TYPE *)0)->MEMBER
: 通过常量指针,访问成员MEMBER&((TYPE *)0)->MEMBER
: 获取MEMBER成员的地址,地址值即为MEMBER成员在TYPE结构中的偏移量(size_t) &((TYPE *)0)->MEMBER
: 将地址值强制转化为size_t类型的整形数
const typeof(((type *)0)->member) * __mptr = (ptr);
结构体中的成员数据可以是任意数据类型,为了让这个宏兼容各种数据类型,定义了一个临时指针变量__mptr
,用来存储结构体成员MEMBER的地址,即存储宏中参数ptr
的值。
必须保证__mptr
和ptr
的指针类型一样,因此使用typeof
关键字,用来获取结构体成员MEMBER的数据类型。
typeof 是 GNU C 新增的一个关键字,用来获取数据类型。