当你开始阅读linux内核的代码的时候,你最终会遇到这个神奇的宏。
三个参数:ptr, type,member, 分别为:成员的指针,包含这个成员的容器的类型,这个成员的名字
返回值:一个指针,指向包含这个成员的容器,如下图
这个宏在已知成员名字及指针,想找到包含自己的结构体的指针的时候很有用(废话),什么时候需要呢?比如在使用c语言写一个适用性强的链表的时候
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
接下来逐步解释
GNU 对C语言有一个扩展,名字为braced-group within expression,{}里面的整个表达式的值是最后一个声明的值。编译器计算evaluate整个{},以最后一个声明/语句作为整个表达式的值。
下面的例子结果是5
int x = ({1; 2;}) + 3; printf("%d\n", x);
这是一个非标准的 GNU C 扩展. 返回唯一参数的类型. 这个宏的语义在http://gcc.gnu.org/onlinedocs/gcc/Typeof.html中与具体描述
int x = 5; typeof(x) y = 6; printf("%d %d\n", x, y);
struct s { char m1; char m2; }; /* This will print 1 */ printf("%d\n", &((struct s*)0)->m2);
下面两个定义是等价的
typeof(((struct s *)0)->m2) c; char c;
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
返回名为MEMBER成员在TYPE类型结构体中的偏移位置.
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
结合以上已经非常容易理解