写在前面
本系列文章的灵感出处均是各个技术书籍的读后感,详细书籍信息见文章最后的参考文献
CONTAINER_OF
在书中发现一个很有意思的宏,以此可以衍生出来其很多的用法,这个宏可以根据某个成员变量的地址得到包含这个成员变量地址的对象的地址。但是,这个过程很危险,慎用哦!
我们先看这个宏的一个依赖宏:OFFSET_OF
,它可以方便的获取此成员变量在这个对象之中的偏移量。
#define OFFSET_OF(TYPE, MEMBER) ((size_t)&(static_cast<TYPE *>(0))->MEMBER)
而CONTAINER_OF
宏可以给定一个成员变量的地址,指定这个成员变量属于哪个对象,指定这个成员变量在对象之中的名称。
#define CONTAINER_OF(ptr, type, member) ({ \
const typeof( (static_cast<type*>(0))->member ) *__mptr = (ptr); \
(type *)((char*)__mptr - OFFSET_OF(type,member) );})
Demo
int main(){
foo my_foo;
foo *p = CONTAINER_OF(&my_foo.a, struct foo, a);
cout<<p<<endl;
}
输出:
0x7ffc75b6dfc0
其他用法
根据作者在书中所属,这个宏被用于以下几种情形:
- 引用计数:对于引用计数结构,可以传递给引用计数一个回调函数,回调函数之中根据这个引用计数对象的地址倒推出包含引用计数的父对象的地址,从而释放资源
void object_release(struct* ref){
Object* object = CONTAINER_OF(ref, Object, myref_);
free(object);
}
- 无关类型的双向链表:只要链表的元素之中包含这个
node_
指针,我们在释放的时候,其实就可以便利node_,调用CONTAINER_OF
去获取这个元素的地址,从而释放资源。
class Object{
public:
some object...
NodeUnit *node_;
};
参考文献
- 《存储技术原理分析》第二章 Linux驱动模型
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)