Linux内核container_of宏

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

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


struct test1
{
    char *pchar ;
    int idata ;
    int *pint ;
};

 

int main()
{
    struct test1 ptest1 ;
    int *p1 = ptest1.pint ;
    printf("the address of ptest1 is %p/n", &ptest1) ;
    printf("the address of p1 is %p/n", p1) ;
    ptest1.pint = 0x55555555 ;
    printf("offsetof(struct test1, pint)=%d/n", offsetof(struct test1, pint)) ;
    printf("container_of(p1, struct test1, pint) = %p/n", container_of(p1, struct test1, pint)) ;  //1
    printf("containerof(ptest1.pint, struct test1, pint)=%p/n", container_of(&ptest1.pint, struct test1, pint)) ;  //2

    printf("containerof(ptest1.pint, struct test1, pint)=%p/n", container_of(ptest1.pint, struct test1, pint)) ;    //3
    return 0 ;
}

 

container_of的作用在于,给定某结构体中字段的地址,能够获取该结构体的起始地址。比如上面的例子中示例2。

the address of ptest1 is 0xbfe5ce38
the address of p1 is 0xb7faeff4
offsetof(struct test1, pint)=8
container_of(p1, struct test1, pint) = 0xb7faefec      //p1的地址往前移8个字节
containerof(&ptest1.pint, struct test1, pint)=0xbfe5ce38    //使用&ptest1.pint作为第一个参数,获得ptest1的地址
containerof(ptest1.pint, struct test1, pint)=0x5555554d    //使用ptest1.pint做第一个参数,只是在该地址的基础上前移8个字节

-------&ptest1.pint是字段的地址,ptest1.pint是字段的值,该值是一个地址。

container_of宏是Linux内核中经常出现的一个东西,原型定义在linux/include/linux/kernel.h中

  1. #define container_of(ptr, type, member) ({ /  
  2.  const typeof( ((type *)0)->member ) *__mptr = (ptr); /  
  3.  (type *)( (char *)__mptr - offsetof(type,member) );})  
#define container_of(ptr, type, member) ({ / const typeof( ((type *)0)->member ) *__mptr = (ptr); / (type *)( (char *)__mptr - offsetof(type,member) );})
ptr指向type(目前发现都是struct 类型)中的一个元素member,通过这个宏,算得此struct的起始地址,比如(type *) a = container_of(ptr, type, member);则a是ptr指向元素所在struct的起始地址。(typeof()是搞一个()中的数据类型)

offsetof也是一个宏,定义在include/linux/stddef.h中

  1. #ifdef __compiler_offsetof  
  2. #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)  
  3. #else  
  4. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
  5. #endif  
#ifdef __compiler_offsetof#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)#else#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)#endif
主要说下 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
((size_t) &((TYPE *)0)->MEMBER)把0地址转化为TYPE结构的指针, 然后获取该结构中MEMBER成员的指针,并将其强制转换为size_t类型。于是,由于结构从0地址开始定义,因此,这样求出的MEMBER成员地址,实际上就是它在结构中的偏移量。

__mptr指向的是一个type结构里typeof(((type *)0)->member)类型member成员的指针,offsetof(type,member)是这个成员在结构中的偏移,单位是字节,所以为了计算type结构的起始地址,__mptr减去它自己的偏移。


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

so:#define offset1(type,member) ((unsigned int)&((type *)0)->member)同样是利用指针索引来进行定位的。  指针 精髓于此?、、


你可能感兴趣的:(struct,include,compiler,linux内核)