关于container_of函数分析

#include <stdio.h>

#define offset_of(type,member) ((int)&(((type *)0)->member))

#define container_of(ptr,type,member) ({\    
    const typeof(((type*)0)->member) *__mptr = ptr;\    
    (type *)((char *)__mptr - offset_of(type,member));\
    })

struct mytest{
    char i;
    int j;
    char *k;
    };
 int main(){
    struct mytest temp;
    struct mytest *p;
    printf("&temp = %p\n",&temp);   
    printf("&temp.k = %p\n",&temp.k);
    printf("&((struct mytest *)0)->k = %d\n",((int)&((struct mytest *)0)->k));
        printf("&temp = %p  \n",container_of(&temp.j,struct mytest,j));
        printf("&temp = %p  \n",container_of(&temp.k,struct mytest,k));
        return 0;}
View Code

(一).分析下宏定义1:

#define offset_of(type,member) ((int)&(((type *)0)->member))

     (type * )0 :强制把0地址转化为type *类型

     &(((type *)0)->member) :将type类型的member成员的地址取出。这里用法很妙,由于type指针地址是0,故其成员地址都是基地址为0加上偏移地址。

     (int)(&(((type *)0)->member)) :将type成员类型地址强制转化为int。

 

(二).分析下宏定义2:

#define container_of(ptr,type,member) ({\	
    const typeof(((type*)0)->member) *__mptr = ptr;\
    (type *)((char *)__mptr - offset_of(type,member));\
    })

       2.1. 分析 const typeof(((type *)0)->member) *__mptr = ptr;

                 const typeof(((type *)0)->member) :typeof是关键字,获取成员类型。此部分是得到宏传过来的成员类型。

                 const typeof(((type *)0)->member) *__mptr = ptr :此部分为什么要重新定义__mptr呢?这就是写linux内核工程师的牛逼,严谨之处。如果开发者使                用时输入的参数有问题:ptr与member类型不匹配,编译时便会有warnning, 但是如果去掉改行,那个就没有了,而这个警告恰恰是必须的(防止出错有不              知道错误在哪里)。。。

       2.2. 分析(type *)((char *)__mptr - offset_of(type,member));

                (char *)__mptr :将成员类型强制转化为char *,如此地址进行加减时以字节为单位

                (char *)__mptr - offset_of(type,member) :计算出结构体首地址,此时地址类型为char *

              (type *)((char *)__mptr - offset_of(type,member)):将char * 强制转化为(type *)

 

索引文献:https://blog.csdn.net/s2603898260/article/details/79371024

 

posted @ 2019-01-04 13:33  三七鸽  阅读(1448)  评论(0编辑  收藏  举报