在linux内核驱动中,我们经常会用到container_of,实际上他是一个宏,其作用是我们可以根据该结构体变量中的某个成员首地址从而获得该结构体变量的首地址。
其具体的定义如下:
#define container_of(ptr, type, member) ({ \ 681 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 682 (type *)( (char *)__mptr - offsetof(type,member) );})
第一个参数ptr: 该结构体变量的一个member的地址;
第二参数type:该结构体变量;
第三个参数member:该结构体中的一个数据成员;
当调用container_of()我们就可以通过ptr获得该结构体的首地址。
1、这里看到了typeof,它是C语言中的一个关键字。可以用来声明某个参数的类型。
看上面粘贴的那段代码:
首先将首地址0强制转换为type类型的指针,指向type结构体中的member数据成员,__mptr指针变量的是定义的一个临时的数据成员类型,该数据类型就是member类型的一个指针,指向ptr。
2、刚好有offsetof,它也是一个宏,其定义如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
这个宏的讲解引用高人的理解,链接如下:
http://blog.csdn.net/tigerjb/article/details/8299584
1>( (TYPE *)0 ) 0地址强制 "转换" 为 TYPE结构类型的指针;
2>((TYPE *)0)->MEMBER 访问TYPE结构中的MEMBER数据成员;
3>&( ( (TYPE *)0 )->MEMBER)取出TYPE结构中的数据成员MEMBER的地址;
4>(size_t)(&(((TYPE*)0)->MEMBER))结果转换为size_t类型。/*该四部为粘贴引用*/
宏offsetof的巧妙之处在于将0地址强制转换为 TYPE结构类型的指针,TYPE结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址