17. containerof

由结构体成员获取机构体指针

定义在include/linux/kernel.h

#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

解析如下

offsetof(type,member)                       #member在结构体成员中的偏移量
typeof( ((type *)0)->member )               #获得member的类型,用于定义一个const变量
(char *)__mptr                              #member的指针, 其实就是 ptr,但是是临时定义的const指针。
(char *)__mptr - offsetof(type,member) );}  #结构体的首地址

offsetof的解析请参考offsetof.md

示例代码如下:可以通过过mem2成员获得sample的首地址

#include  <stdio.h>

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({         \
    const typeof( ((type *)0)->member ) *__mptr = (ptr); \
    (type *)( (char *)__mptr - offsetof(type,member) );})

int main(void)
{
    struct sample {
        int mem1;
        char mem2;
    };

    struct sample sample1;

    printf("Address of Structure sample1 (Normal Method) = %p\n", &sample1);

    printf("Address of Structure sample1 (container_of Method) = %p\n",
                            container_of(&sample1.mem2, struct sample, mem2));

    return 0;
}

为什么要定义一个临时变量,换成下面这种写法,结果是一样的。现在还不知道区别在哪里

#include  <stdio.h>

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({      \
        (type *)( (char *)ptr - offsetof(type, member) ); \
})

int main(void)
{
    struct sample {
        int mem1;
        char mem2;
    };

    struct sample sample1;

    printf("Address of Structure sample1 (Normal Method) = %p\n", &sample1);

    printf("Address of Structure sample1 (container_of Method) = %p\n",
                            container_of(&sample1.mem2, struct sample, mem2));

    return 0;
}