本系列文章的灵感出处均是各个技术书籍的读后感,详细书籍信息见文章最后的参考文献
在书中发现一个很有意思的宏,以此可以衍生出来其很多的用法,这个宏可以根据某个成员变量的地址得到包含这个成员变量地址的对象的地址。但是,这个过程很危险,慎用哦!
我们先看这个宏的一个依赖宏:OFFSET_OF
,它可以方便的获取此成员变量在这个对象之中的偏移量。
/*
* @brief OFFSET_OF 获得member在type类型里面的偏移量
* @param[in] Type: 类型
* @param[in] MEMBER: 成员变量的名称
*/
#define OFFSET_OF(TYPE, MEMBER) ((size_t)&(static_cast<TYPE *>(0))->MEMBER)
而CONTAINER_OF
宏可以给定一个成员变量的地址,指定这个成员变量属于哪个对象,指定这个成员变量在对象之中的名称。
/**
* @brief CONTAINER_OF - 通过三个参数,返回指向数据结构的指针
* @param[in] ptr: 数据结构中指向某一成员的指针
* @param[in] type: 数据结构类型
* @param[in] member: 在数据结构中的成员
* @note CONTAINER_OF 可以根据某个成员变量的地址得到包含这个成员变量地址的对象的地址。这个过程很危险慎用哦!
* @return 成员变量的地址
*/
#define CONTAINER_OF(ptr, type, member) ({ \
const typeof( (static_cast<type*>(0))->member ) *__mptr = (ptr); \
(type *)((char*)__mptr - OFFSET_OF(type,member) );})
int main(){
foo my_foo;
foo *p = CONTAINER_OF(&my_foo.a, struct foo, a);
cout<<p<<endl;
}
输出:
0x7ffc75b6dfc0
根据作者在书中所属,这个宏被用于以下几种情形:
//这依赖myref_是对象的公有成员变量
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驱动模型