关于container_of等宏的整理

来源:互联网 发布:淘宝买家贷款那里申请 编辑:程序博客网 时间:2024/06/05 18:38

        一直很是疑惑container_of是什么意思,最近看了一些资料,整理一下。

     1)typeof

     首先,我们要知道typeof,它是gcc的C语言扩展保留字,用于声明变量类型。typeof的参数可以是两种形式:表达式类型例如:

    typeof(x)

    这里假设x是一个函数指针,这样就可以得到这个函数返回值的类型了。
    如果将typeof用于表达式,则该表达式不会执行。只会得到该表达式的类型。以下示例声明了int类型的var变量,因为表达式foo()是int类型的。由于表达式不会被执行,所以不会调用foo函数。


    extern int foo();
    typeof(foo()) var;

   下面是用类型作参数的例子:
    typeof(int *) a,b;
   等价于:
    int *a,*b;

   下面是两个等效声明,用于声明int类型的变量a。
    typeof(int) a; /*int类型*/
    typeof('b') a; /* GCC中这个表达式的类型是int(自动提升为int),注意typeof(char)和typeof('b')得到的不是一样的,这个用sizeof可以看出来*/

    一般情况下用typeof就可以了,但是如果要于ISO C兼容的话,最好是用双下划线的形式:__typeof__。
typeof和typedef很像,事实上,只要能用typedef的地方就可以用typeof。


    把y定义成一个字符指针数组:
     typeof(typeof(char *))[4] y;
    这与下面的定义等价:
    char *y[4];

    在宏声明中使用typeof
    typeof构造的主要应用是用在宏定义中。可以使用typeof关键字来引用宏参数的类型。因此,在没有将类型名明确指定为宏实参的情况下,构造带有所需类型的对象是可能的。
   下面是一个交换两个变量的值的宏定义:
    #define SWAP(a,b) {\
       typeof(a) _t=a;\
       a=b;\
       b=_t;}
       这个宏可以交换所有基本数据类型的变量(整数,字符,结构等)

       原文参考:http://blog.csdn.net/wslong/article/details/7728811

2)#define offsetof(TYPE, MEMBER) ((size_t)  &((TYPE *)0)->MEMBER)
     获取TYPE类型中成员MEMBER的相对偏移量,如果基址为0,那么地址&((TYPE *)0)->MEMBER转换为size_t后就是此成员的偏移量了。这里的0作为起始地址用,来计算偏移量,如果用其它数字代替offsetof得到的数值要减去这个数字才是真正的偏移量,所以这里用0是最佳的选择。

3)const  typeof( ((type *)0)->member )    *__mptr = (ptr);

     定义一个__mptr指针变量,类型和member的类型一样
     typeof是获得一个变量的类型,((type *)0)->member 则是tpye类型中的member 变量,一般type为结构体类型,member 则为其中的变量。

4)#define container_of(ptr, type, member) ({   \
          const  typeof( ((type *)0)->member )  *__mptr = (ptr); \
          (type *)( (char *)__mptr - offsetof(type,member) );})
     (type *)( (char *)__mptr - offsetof(type,member) );意思是__mptr的地址减去member在该struct中的偏移量得到的地址, 再转换成type型指针. 该指针就是member的入口地址了.

  

      也就是说,container_of是通过ptr获取到了type成员member的入口地址,然后再获得type结构的地址。

      container_fo举例:
    struct demo_struct {

      type1 member1;
      type2 member2;
      type3 member3;
      type4 member4;
   };

   struct demo_struct demo;
   同时,如果在另一个地方,获得了变量demo中的某一个域成员变量的指针,比如:
     type3 *memp = get_member_pointer_from_somewhere();
    此时,如果需要获取指向整个结构体变量的指针,而不仅仅只是其某一个域成员变量的指针,我们就可以这么做:
    struct demo_struct *demop = container_of(memp, struct demo_struct, member3);

 

 

原创粉丝点击