《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 \n",off);  //6
    off = offsetof(S5,b);
    printf("  off = %d \n",off);  //12

    S5 s5;
    S5 *p = NULL;
    printf("  s5  = %p \n",&s5);  //0x7ffc5c373c70

    p = container_of(&s5.b,S5,b);

    printf("  p  = %p \n",p);     //0x7ffc5c373c70

}

#pragma pack()

 

posted @ 2020-11-15 11:42  xuxianshen  阅读(157)  评论(0编辑  收藏  举报