container_of使用小结

 先上演示代码

#include <stdio.h>
#include <stdlib.h>

/* offsetof example */
#include <stddef.h>     /* offsetof */

//#define offsetof(type, member) (size_t)&(((type*)0)->member)
/**
 * container_of - 通过结构体的一个成员获取容器结构体的指针
 * @ptr: 指向成员的指针。
 * @type: 成员所嵌入的容器结构体类型。
 * @member: 结构体中的成员名。
 *
 */
#define container_of(ptr, type, member) ({ 
        const typeof( ((type *)0)->member ) *__mptr = (ptr); 
       (type *)( (char *)__mptr - offsetof(type,member) );})

typedef struct student_info
{
    int  id;
    char name[10];
    int  age;
}student_info;

#define DEBUG_COUT(var) do{printf(#var"= %d
",(int)var);}while(0)
#define DEBUG_POINT(var) do{printf(#var"= %p
",var);}while(0)    
int main(void)
{

    printf ("************offsetof example************
");
    DEBUG_COUT(offsetof(student_info,id)); 
    DEBUG_COUT(offsetof(student_info,name)); 
    DEBUG_COUT(offsetof(student_info,age));     
    printf ("************container_of example************
");
    student_info *stu = (student_info *)malloc(sizeof(student_info));    
    stu->age = 18;
    student_info *ptr = container_of(&(stu->age), student_info, age);      
    DEBUG_POINT(stu);//printf("stu address:%p
", stu);
    DEBUG_POINT(ptr);//printf("ptr address:%p
", ptr);
    DEBUG_COUT(ptr->age);

    system("pause");
    return 0;
}
make一下并且测试一下

参考分析Linux内核container_of详解(图解)

    /**
     * container_of - 通过结构体的一个成员获取容器结构体的指针
     * @ptr: 指向成员的指针。
     * @type: 成员所嵌入的容器结构体类型。
     * @member: 结构体中的成员名。
     *
     */
    #define container_of(ptr, type, member) ({ 
        const typeof( ((type *)0)->member ) *__mptr = (ptr); 
        (type *)( (char *)__mptr - offsetof(type,member) );})

  这个宏的作用其实很简单,就是通过一个容器(结构体)中某个成员的指针得到指向这个容器(结构体)的指针,简单的说就是通过成员找容器。

 
这个宏的实现代码也就只有两行,下面仔细分析一下:
(1)const typeof( ((type *)0)->member ) *__mptr = (ptr);
定义一个中间变量__mptr,它等于提供给宏的参数ptr,也就是指向某个成员的指针。这个中间变量的命名意义是:
"__"代表内部使用,内核编程中常常这么做;
“m”代表middle。
 
(2)(type *)( (char *)__mptr - offsetof(type,member) );
这行代码的作用是通过中间变量__mptr(指向某个成员的指针)减去这个成员在容器(结构体)中的偏移来得到指向容器(结构体)的指针。
这里注意偏移的获取offsetof宏的实现
 
红色代表输出,蓝色代表输入,黑色代表中间变量
原文地址:https://www.cnblogs.com/libra13179/p/9183650.html