这两个宏的源代码如下,大家用到的使用的一个方法是可以直接复制到自己的代码中使用。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#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)
(TYPE *0)我们即从地址ox0处开始建立一个TYPE类型所需的内存空间用来存储一个TYPE类型的数据,该类型一般为结构体类型或者是类类型的数据(这样子才有数据成员嘛),(TYPE *0)->MEMBER也即是访问该类型的MEMBER成员变量,最后获取该成员变量MEMBER的地址,也即是&((TYPE *0)->MEMBER),然后强制转换为size_t类型,关于size_t类型的数据一般都是内存的字节数,因为此时[MEMBER成员的地址]也就是[MEMBER成员]距离[该类/结构体的地址]的字节数。
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
然后这里的宏有3个参数,涉及到offsetof宏所需的参数,多了一个ptr指针,ptr指向实际的数据结构(类/结构体)某个成员变量的指针,然后对这个之定义一个(((TYPE *)0)->MEMBER) 类型数据另外起一个名字为__mptr的指针,__mptr赋值为ptr,然后给再减去offsetof()宏计算出来的字节数,得到了结构体/类的数据的指针。
重点在理解内存模型,内存模型懂了,自然理解这两个宏。