zoukankan      html  css  js  c++  java
  • 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宏的实现
     
    红色代表输出,蓝色代表输入,黑色代表中间变量
  • 相关阅读:
    JS重写alert,保证弹窗错误的友好性
    wpf窗体中复合控件焦点控制
    mybatis特殊字符转义
    SpringMVC HandlerMethodArgumentResolver自定义参数转换器
    IntelliJ IDEA创建maven web项目
    shiro app
    Linux查看日志定位问题
    Flask中使用Flask-Migrate扩展迁移数据库
    flask + pymysql操作Mysql数据库
    HTTP
  • 原文地址:https://www.cnblogs.com/libra13179/p/9183650.html
Copyright © 2011-2022 走看看