container_of 主要用于解决
已知
- 某个成员的地址: ptr
- 该成员的名称:member;
- 包含该成员的类型:struct container{…, member,…};
得到
- 包含该成员的类型的实例的地址
简释如下:
#include<stdio.h>
#include <stddef.h>
/**< build in macro
* #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
*/
/**<
* 1. 将任意地址强转为包含该成员的类型的指针:(type*)0xFFFFFFFF; (一般写(type*)0)
* 2. 用得到的指针访问该成员: ((type*)0xFFFFFFFF)->member, 相当于得到该成员变量;
* 3. 用typeof推断该成员变量的类型:typeof( ((type *)0xFFFFFFFF)->member );
* 4. 定义该成员变量类型(第3步推断出的类型)的指针变量: __mptr;
* ----------------------------------以上4步推断出成员的类型
* 5. 该成员的地址赋值给__mptr;
* 6. 该成员的地址减去该成员相对于包含该成员的类型的偏移:offsetof(type,member);得到
* 包含该成员的类型的实例对象的首地址;
* 7. 将该地址转为包含该成员的类型。OVER
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0xFFFFFFFF)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct test {
int ma;
int mb;
int mc;
};
int main()
{
struct test t; ///< 实例对象
//const typeof(t.mb) *pmb = &(t.mb); ///< 已知成员mb的地址
int *pmb = &(t.mb); ///< 已知成员mb的地址
struct test *tp = container_of(pmb, struct test, mb); ///< 由该对象的成员地址得到实例对象的地址
printf("object addr: %p\n", &t);
printf("container_of: %p\n", tp);
return 0;
}
这里我们已知:类型test的实例对象t的成员mb的地址pmb,用container_of得到该实例对象t的首地址tp。