文章目录
- `rt_container_of` 宏概述
- 步骤1:计算成员偏移量
- 步骤2:将成员指针转换为字节指针
- 步骤3:计算结构体的地址
- 步骤4:返回结构体指针
- 代码示例
- 宏的内部实现解析
rt_container_of
宏概述
rt_container_of
宏是一个非常实用的宏定义,它通过成员指针反向推导出整个结构体变得非常简洁和高效。这在内核编程和驱动开发中经常出现。
rt_container_of
宏的定义如下:
#define rt_container_of(ptr, type, member) \((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
该宏的目的是通过给定成员指针 ptr
,计算出包含该成员的结构体的指针。现在分步骤分析宏的工作原理。
步骤1:计算成员偏移量
首先,((type *)0)
表示一个类型为 type
的空指针。这实际上是将整数 0
强制转换为指向指定类型结构体的指针。接着,&((type *)0)->member
计算出该结构体成员 member
在结构体中的偏移量。此时,&((type *)0)->member
的作用是通过一个虚拟的零地址计算成员 member
在结构体中的位置。
步骤2:将成员指针转换为字节指针
接下来,宏将 ptr
转换为 char *
类型。这一步是为了按字节来进行地址的计算,因为 char
类型的指针可以进行字节级的地址偏移。
步骤3:计算结构体的地址
然后,通过 ptr
和成员的偏移量,利用 (char *)(ptr) - offset
来计算整个结构体的起始地址。这一步将成员指针向回移动 member
在结构体中的偏移量,从而得到了包含该成员的整个结构体的地址。
步骤4:返回结构体指针
最后,宏将计算出来的地址转换为 type *
类型,得到结构体的指针。
代码示例
假设我们有如下的结构体定义:
// 定义一个结构体
struct example {int x;int y;
};
接下来,我们初始化结构体实例并取得成员 y
的指针:
struct example obj;
obj.x = 100;
obj.y = 200;// 假设我们有一个指向成员 y 的指针
int *p_y = &obj.y;
此时,我们有一个指向成员 y
的指针 p_y
,但我们希望根据该指针反推出整个结构体的指针。此时就可以使用 rt_container_of
宏来实现这一功能:
struct example *p_obj;
p_obj = rt_container_of(p_y, struct example, y);
宏的内部实现解析
((type *)0)
将0
强制转换为指向struct example
类型的指针。&((type *)0)->y
计算出成员y
在struct example
中的偏移量。(char *)(p_y)
将成员指针p_y
转换为char *
类型,便于按字节计算地址。(char *)(p_y) - offset
通过减去偏移量,回退到结构体的起始地址。- 最后,将计算出的地址转换为
struct example *
类型,得到整个结构体的指针。
至此,我们成功地从 p_y
反推出了结构体 obj
的指针 p_obj
。