zoukankan      html  css  js  c++  java
  • 神奇的container_of

    container_of是linux内核中常用的一个宏,这个宏的功能是,根据某个结构体字段的指针,找到对应的结构体指针。


    话不多说,先上源码:

    /**
    * container_of - cast a member of a structure out to the containing structure
    * @ptr:        the pointer to the member.
    * @type:       the type of the container struct this is embedded in.
    * @member:     the name of the member within the struct.
    *
    */
    #define container_of(ptr, type, member) ({                      
            const typeof( ((type *)0)->member ) *__mptr = (ptr);    
            (type *)( (char *)__mptr - offsetof(type,member) );})

    第一个参数为指向结构体中的成员的指针,第二个参数为结构体类型,第三个参数为结构体成员的名字。

     
    如图,一个结构体struct a中包含三个成员b,c,d,一个指向成员c的指针p_c,通过 container_of(p_c,  struct  a,  c )就可以计算出指向c所在的结构体的指针p_a


    原理说明:
    这个宏的原理是结构体成员指针ptr,减去结构体成员与此结构体首地址的偏移量(这个偏移量由offsetof宏获得),就得出了结构体首地址。这个功能是由宏声明的第三行实现的。
    那么宏声明的那二行是干什么用的呢?它仅仅是把ptr重新赋值给了__mptr,看似没用。实际上这里起到了给开发者提醒的功能。如果开发者传入的ptr指针指向的类型,与结构体中成员的类型不符,编译器在这里会打印一条warning,提示开发者可能存在的错误。


    测试代码:
    #include <stdio.h>
    #include <linux/kernel.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) );})
    
    struct a {
                     int b ;
                     int c ;
                     int d ;
    };
    
    int main( int argc, char *argv[])
    {
                     struct a a_obj, *p_a;
                     int *p_c;
    
                    p_c = &a_obj. c ;
                    p_a = container_of(p_c, struct a, c);
    
                     printf ("a_obj addr:%x
    a_obj addr obtained by container_of: %x
    ", ( unsigned int )&a_obj, ( unsigned int )p_a);
    
                     return 0;
    }
    
    打印结果:
    a_obj addr:bfffed98
    a_obj addr obtained by container_of: bfffed98



  • 相关阅读:
    C语言I博客作业02
    C语言II—博客作业01
    学期总结
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I 博客作业04
    C语言II博客作业04
    C语言II博客作业03
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3258262.html
Copyright © 2011-2022 走看看