RT-Thread 的继承机制通过 结构体内嵌 和 地址计算宏 实现,其核心设计目标是 零内存开销的动态类型转换 和 父子类数据无缝访问
一、结构体内嵌的内存布局
1规则
1.1父类实例必须作为子类结构体的第一个成员
struct Parent { int a; };
struct Child {
struct Parent parent; // 必须为首成员
int b;
};
内存对齐保证:父类首地址与子类首地址重合。
- C 语言标准规定:结构体的首成员地址等于结构体自身的地址(
&child == &child.parent
)。
2指针强制转换
2.1直接访问父类数据:
struct Child child;
struct Parent *parent_ptr = (struct Parent *)&child; // 合法转换
无需计算偏移量,直接通过类型转换访问父类字段(如 parent_ptr->a
)。
二、rt_container_of
宏的底层原理
1.宏定义分解
#define rt_container_of(ptr, type, member) \
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
2.步骤拆解
2.1计算成员偏移量:
&((type *)0)->member
- 将
0
强制转换为type *
类型指针,此时结构体起始地址为0
。 - 取成员
member
的地址,等价于member
在type
中的偏移量(如offsetof(type, member)
)。
2.2地址逆向计算:
(char *)(ptr) - offset
- 将传入的成员指针
ptr
转换为char *
(确保按字节计算偏移)。 - 减去成员偏移量,得到包含该成员的父类结构体首地址。
2.3类型转换:
(type *)result_ptr
- 将计算结果转换为
type *
类型,即子类结构体指针。