• 《C语言笔记:offsetof宏和container_of宏》


    一,offsetof宏

      1,作用:计算结构体中某个元素与结构体首地址的偏移量。

      2,原理:虚拟一个0地址处的结构体类型变量type,然后用type.member的方式来访问那个member元素,继而得到member相对于整个变量首地址的偏移量。

      3,自己实现:offsetof(type,member)    (  (unsigned long) &((type *)0)->member )  

      4,分布分析:(type *)0  将地址0强制转换为一个结构体类型变量,((type *)0)->member 指向结构体变量的成员,&((type *)0)->member 得到这个成员变量的地址,这个地址是从0地址开始的,故而便是这个成员变量相对于结构体首地址的偏移量。

    二,container_of宏

      1,作用:知道一个结构体中某个成员变量的指针,来反推这个结构体的指针。使得可以从一个成员变量的指针得到整个结构体的指针,继而得到结构体中其他元素的指针。

      2,typeof关键字的作用是:typeof(a)由变量a得到a的类型,由变量名得到变量的数据类型。

      3,实现:

          #define container_of(ptr,type,member) ({

                            const typeof(((type *)0)->member) *mptr = (ptr);
                            (type *)((unsigned long)mptr - offsetof(type, member));

                           })

      4,原理:先用typeof得到member元素的类型,然后定义成一个这个类型的指针,然后用这个指针减去该元素相对于整个结构体的偏移量(用offsetof宏得到),减去之后得到的就是整个结构体变量的首地址了,再把这个地址强制类型转换为type *就是结构体变量的指针了。

      

    #include<stdio.h>
    
    
    #pragma pack(4)
    
    #define offsetof(type,member) ((unsigned long)&((type *)0)->member)
    
    #define container_of(ptr,type,member) ({const typeof(((type *)0)->member) *mptr = (ptr);
                                                (type *)((unsigned long)mptr - offsetof(type, member));})
    
    typedef struct Mystruct1
    {                    //        1字节    4字节     8字节
        int a;           //        4        4        4
        char b;            //        1        1+1        1+1
        short c;        //        2        2        2
    }S1;
    
    typedef struct Mystruct5{
        char a;                // 1+3   1+3
        S1 s1;                // 8     8
        double b;            // 8     8    
        int c;                // 4     4+8
    }S5;
    
    
    int main()
    {
        int off;
        
        off = offsetof(S1,c);
        printf("  off = %d 
    ",off);  //6
        off = offsetof(S5,b);
        printf("  off = %d 
    ",off);  //12
    
        S5 s5;
        S5 *p = NULL;
        printf("  s5  = %p 
    ",&s5);  //0x7ffc5c373c70
    
        p = container_of(&s5.b,S5,b);
    
        printf("  p  = %p 
    ",p);     //0x7ffc5c373c70
    
    }
    
    #pragma pack()
  • 相关阅读:
    MYSQL批量插入数据库实现语句性能分析【转】 批量插入!程序里面对于数据库插入的功能尽量用【异步处理+批量插入+(事务)】
    移动端如何解决页面返回上次浏览位置问题
    php对接java接口
    php后端遇到的问题
    jquery 判断字符串长度
    phpExcel常用方法详解
    html 手机端适配不同手机高度 ,把内容居中显示
    html 手机端 生成海报
    没错,老师就是个勤奋负责有良心的职业,不,的人
    睡眠是自然的第二道菜
  • 原文地址:https://www.cnblogs.com/xuxianshen/p/13976213.html
Copyright © 2020-2023  润新知