zoukankan      html  css  js  c++  java
  • container_of学习笔记

    最近在学习c语言宏编程,看到了container_of宏,深入学习了一天,做个笔记留念。

    1、看一下书上写的container_of的版本:

    #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)); })

    2、举一个实例:

    int main(int argc, char *argv[])
    {
        struct test{
            int num;
            char ch; 
        }t1={100,'c'};
        char *pch=&t1.ch;
        struct test *ptt=container_of(pch,struct test,ch);
        printf("num=%d
    ",ptt->num);
    
        return 0;
    }

    替换后的结果:

    int main(int argc, char *argv[])
    {
     struct test{
      int num;
      char ch;
     }t1={100,'c'};
     char *pch=&t1.ch;
     struct test *ptt=({ const typeof(((struct test *)0)->ch) *__ptmp=(pch); (struct test *)((char *)__ptmp - ((size_t) &((struct test *)0)->ch)); });
     printf("num=%d
    ",ptt->num);
    
     return 0;
    }         

    如果替换后的结果你还能看懂,说明你是真明白了,呵呵,有没有兴趣自己写一遍替换后的代码?

    3、多余的不说了,网上有的是讲解的,这里就说二点:

       1、container_of宏第一步是做类型检查的,也就是检查ptr是否是指向结构成员member的,如果我们用typeof求出来的类型和ptr不一致,那么编译器会报错。为啥要做这个检查呢?因为ptr和member都是人工输入的参数,宏要保证它们是结构体成员和其相关联的指针,这个宏才有意义,所以类型检查是必须的。

          2、第二步相减时,把mptr指针强转成(char *)是因为,char指针减法只移一个字节,如果这样才可能得出准确的地址,否则,改为int类型,在减1就移动4个就乱了。

    4、我有研究了最新4.12kernel的该宏,发现有了变化:

    /**
     * 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) ({                
        void *__mptr = (void *)(ptr);                    
        BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&    
                 !__same_type(*(ptr), void),            
                 "pointer type mismatch in container_of()");    
        ((type *)(__mptr - offsetof(type, member)));

    哇,这里有出现一个新宏:__same_type,赶紧用ctags查一下定义,在include/linux/compiler.h中:

    /* Are two types/vars the same type (ignoring qualifiers)? */
    #ifndef __same_type
    # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))                  
    #endi

    有2个新变化,显得更加高大上了,第一,用void *取代了char *来做减法,第二,用__same_type宏来做类型检测,显得更加的直观明了,错了还可以有提示。

  • 相关阅读:
    hdu 5646 DZY Loves Partition
    bzoj 1001 狼抓兔子 平面图最小割
    poj 1815 Friendship 最小割 拆点 输出字典序
    spoj 1693 Coconuts 最小割 二者取其一式
    hdu 5643 King's Game 约瑟夫环变形
    约瑟夫环问题
    hdu 5642 King's Order
    CodeForces 631C Report
    1039: C语言程序设计教程(第三版)课后习题9.4
    1043: C语言程序设计教程(第三版)课后习题10.1
  • 原文地址:https://www.cnblogs.com/litifeng/p/7690585.html
Copyright © 2011-2022 走看看