container_of宏

17.container_of宏
这个宏的是根据传进去的结构体中的某个成员的指针来返回该结构体的首地址,以后我们就可以通过结构体的首地址来方便访问该结构体中的任何成员了。
这个宏工作的原理:先用typedef得到member元素的类型定义成一个指针,然后用这个指针减去该元素相对于整个结构体变量的偏移量(偏移量用offsetof宏得到的),减去之后得到的就是整个结构体变量的首地址了,再把这个地址强制类型转换为type*即可。


#define container_of(ptr, type, member)   ({ \
const typeof(((type *)0) ->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member));})
解析:
typeof(a):由变量a得到a的类型,typeof就是由变量名得到变量数据类型的。
offsetof(type, member):得到type数据结构里的元素member相对该数据结构的首地址的偏移量。
(type *)0:将地址0强制转换成(type)类型的指针;
((type *)0) ->member):将该指针指向member成员;
typeof(((type *)0) ->member):获取member成员这个变量的类型;
const typeof(((type *)0) ->member) * __mptr:用来定义一个指针变量__mptr;
const typeof(((type *)0) ->member) * __mptr = (ptr):__mptr指向ptr;
(char *)__mptr:取__mptr的地址;
offsetof(type, member)):member成员相对数据结构体首地址的偏移量;
(char *)__mptr - offsetof(type, member):得到数据结构的首地址;
(type *)(char *)__mptr - offsetof(type, member):将改地址转换为type *型的。


struct mystruct
{
char a; // 0
int b; // 4
short c; // 8
};


// TYPE是结构体类型,MEMBER是结构体中一个元素的元素名
// 这个宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int
#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)


// ptr是指向结构体元素member的指针,type是结构体类型,member是结构体中一个元素的元素名
// 这个宏返回的就是指向整个结构体变量的指针,类型是(type *)
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })


int main(void)
{
struct mystruct s1;
struct mystruct *pS = NULL;

short *p = &(s1.c); // p就是指向结构体中某个member的指针

printf("s1的指针等于:%p.\n", &s1);

// 问题是要通过p来计算得到s1的指针
pS = container_of(p, struct mystruct, c);
printf("pS等于:%p.\n", pS);
}

猜你喜欢

转载自blog.csdn.net/qq_20725221/article/details/51476467