搜尋此網誌

2011年5月19日 星期四

container_of()

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>

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


    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
*/



struct test {
    int a;
    char *b;
};

int main(int argc, char *argv[])
{
    //通过struct test成员b返回struct的入口地址
//container_of(&tmp.b, (struct test), b); 
 
    struct test tmp;
    struct test *ptmp;
    int offset;
    tmp.a = 10;

    printf("&tmp.a = %02x, &tmp.b = %02x\n", &tmp.a, &tmp.b);

    //定义一个 _mptr指针, 类型为struct test结构体中b成员的类型
    //typeof 为获取(((struct test*)0)->b)的类型,此处此类型为char*
    const typeof(((struct test *)0)->b) *_mptr = &tmp.b;
    printf("_mptr = %02x\n", _mptr);


    //#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    //TYPE是某struct的类型 0是一个假想TYPE类型struct,MEMBER是该struct中的一个成员. 
    //由于该struct的基地址为0, MEMBER的地址就是该成员相对与struct头地址的偏移量.
    offset = (int)(&((struct test *)0)->b);
    printf("offset = %d\n", offset);

    //_mptr的地址减去MEMBER在该struct中的偏移量得到的地址, 再转换成type型指针. 该指针就是struct的入口地址了.
    ptmp = (struct test *)((char *)_mptr - offset);
    
    printf("tmp = %02x, ptmp = %02x\n", &tmp, ptmp);
    printf("ptmp->a = %d\n", ptmp->a);
    return 0;
}

输出结果:
$ ./a.out 
&tmp.a = bfffe6a0, &tmp.b = bfffe6a4
_mptr = bfffe6a4
offset = 4
tmp = bfffe6a0, ptmp = bfffe6a0
ptmp->a = 10

沒有留言:

張貼留言