• container_of


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

    它的作用显而易见,那就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针

    1 #undef offsetof
    2 #ifdef __compiler_offsetof
    3 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
    4 #else
    5 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    6 #endif

    需要注意的是,要使用container_of,则type中成员member不能为指针。(若其为指针,则ptr为指针的指针,为程序带来复杂性)。

    此处错误应删除(指针成员与非指针成员同等处理即可)。例程中如下代码即可验证,但是若为指针时container_of()的第一参数ptr存储的是member成员的地址(即指针的地址),而非指针值。

    #if 1
        stu2.scc="ABCD";
        str = &(stu2.scc);
        pstu1 = container_of(str, stu, scc);
        printf("The score is %s
    ", pstu1->scc);
    #endif

    详细示例参考“设备结构体设计思考”。

    #include <stdio.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) );})
    
    typedef struct {
        char score;
    } core_grade;
    
    typedef struct {
        int no; 
        int age;
        core_grade grade;
        char sc; 
      char *scc; } stu,
    *pstu; int main(int argc, char *argv[]) { stu stu1, stu2, *pstu1=NULL; char *pch = NULL;
      void *str = NULL; // save addr
    #if 0 stu1.grade.score='A'; pch = &(stu1.grade.score); pstu1 = container_of(pch, stu, score); printf("The score is %c ", (pstu1->grade).score); #endif #if 1 stu1.sc='A'; pch = &(stu1.sc); pstu1 = container_of(pch, stu, sc); printf("The score is %c ", pstu1->sc); #endif

     #if 1
      stu2.scc="ABCD";
      str = &(stu2.scc);
      pstu1 = container_of(str, stu, scc);
      printf("The score is %s ", pstu1->scc);
     #endif

        return 0;
    }

    上述代码同时验证了,container_of不能穿透结构体(#if 0...#endif)。

    上述结论错误,container_of()的第二个参数type和第三个参数member必须是直接的包含关系时才可以;若是间接包含,则第三个参数必须拓展到直接包含的成员引用才可以。

    上述code中container_of报错:

    pstu1 = container_of(pch, stu, score);
    structinc.c:6:30: error: ‘stu {aka struct <anonymous>}’ has no member named ‘score’
         const typeof( ((type *)0)->member ) *__mptr = (ptr);    

    但改为如下code则编译成功:

    pstu1 = container_of(pch, stu, grade.score);

    参考:设备接口体应用container_of的思考

  • 相关阅读:
    python的input获取用户输入
    pyinstaller打包成功的.exe,本机运行正常,在别的电脑上运行报错Failed to execute script ...
    Shell应用:批量将文件编码由gbk转utf8
    不伤眼睛的文字背景色 豆沙绿RGB值为(199,237,204)
    javascript禁用backspace回退,shift+backspace前进,F5等刷新页面功能
    crontab实行shell乱码问题解决
    linux C 函数大全 .
    Web服务器:shell字符串处理
    Linux C编程一站式学习 .
    crontab中date的用法
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/5496462.html
Copyright © 2020-2023  润新知