当前位置:首页 > 富博FUBO官方网址 >
富博FUBO官方网址
offsetof宏:结构体成员相对结构体的偏移位置container_of:根据结构体成员的地址来获取结构体的地址 offsetof 宏 原型: container_of 宏 原型:linux-4.18.5 网上所见更多是底下这个版本: 第一部分: 因此#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
(TYPE *)0
非常巧妙,告诉编译器有一个指向结构体 TYPE 的指针,其地址是0,然后取该指针的 MEMBER 地址 &((TYPE *)0)->MEMBER
,因为基址是0,所以这时获取到的 MEMBER 的地址就是相当于在结构体 TYPE 中的偏移量了。Example:#include <stdlib.h>#include <stdio.h>#include <stddef.h>struct TYPE{ int mem; int member;};int main(){ struct TYPE type; printf("&type = %p", &type); printf("&type.member = %p", &type.member); printf("&((struct type *)0)->member = %lu", ((size_t)&((struct TYPE *)0)->member) ); printf("offsetof(struct TYPE member) = %zd", offsetof(struct TYPE, member)); return 0;}/*result:&type = 0x7ffc1104a110&type.member = 0x7ffc1104a114&((struct type *)0)->member = 4offsetof(struct TYPE member) = 4*/
/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. * */#define container_of(ptr, type, member) ({ void *__mptr = (void *)(ptr); BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && !__same_type(*(ptr), void), "pointer type mismatch in container_of()"); ((type *)(__mptr - offsetof(type, member))); })
#define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
void *__mptr = (void *)(ptr);
或const typeof( ((type *)0)->member ) *__mptr = (ptr);
两个的差别在于 __mptr 的类型一个是 void * ,一个是 type *。void * 较为容易理解,下面来看看 type *:关于 typeof 关键字其作用是返回变量的类型,简单理解就是如下,详细可参见GCC typeof在kernel中的使用——C语言的“编译时多态”int a;typeof(a) b; //这等同于int b;typeof(&a) c; //这等同于int* c;
const typeof( ((type *)0)->member ) *__mptr = (ptr);
的作用就是通过 typeof 获取结构体成员 member 的类型,然后定义一个这个类型的指针变量 __mptr 并将其赋值为 ptr。第二部分:(type *)( (char *)__mptr - offsetof(type,member) )
,通过offsetof
宏计算出 member 在 type 中的偏移,然后用 member 的实际地址__mptr
减去偏移,得到 type 的起始地址。从上面关于offsetof
宏的 Example 也可以验证这一点:&type.member = 0x7ffc1104a114 - &((struct type *)0)->member = 4 = &type = 0x7ffc1104a110