Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
链表
系统中的链表rt_list_t
发布于 2024-04-01 11:29:07 浏览:687
订阅该版
一般地,C语言实现双向链表是这样定义节点的 ```c struct list_node { int data; struct list_node *next; // 指向前一节点 struct list_node *prev; // 指向后一节点 }; ``` 而在rt-thread中,链表定义是这样的: ```c struct rt_list_node { struct rt_list_node *next; struct rt_list_node *prev; }; typedef rt_list_node rt_list_t; ``` 从这个定义看,链表节点结构体的定义中不带数据,仅仅是链表而已,很抽像,但是这样的好处是不用针对具体的对象定义节点结构体了。一个例子: ```c struct obj1_node { int data; rt_list_t list; }; struct obj2_node { float data; rt_list_t list; }; // 这样就可以了,而不需要这样定义 struct obj1_node { int data; struct obj1_node *next; // 指向前一节点 struct obj1_node *prev; // 指向后一节点 }; struct obj2_node { int data; struct obj2_node *next; // 指向前一节点 struct obj2_node *prev; // 指向后一节点 }; ``` 两个方式的对比 ![Pasted image 20240329174057.png](https://oss-club.rt-thread.org/uploads/20240401/ca4fcd1b8f3be726f3bc9e72f53a79d6.png.webp) 这样的话,节点的指针只指向结构体的`list`成员, 要寻址结构体有用成员数据,还要作一下运算。下面的宏就实现了这个功能 ```c #define rt_container_of(ptr, type, member) \ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) ``` 下面例子分析 ```c struct obj1_node { int data; rt_list_t list; }; ``` 假如`list`的地址是12, 很明显,因为`int`类型占4个字节,`data`成员的地址是12-4=8, 也是这个node的地址。所以关键是我们要知道某个node struct的头地址离list有“多远” ,想要通过list成员的地址知道这个节点的地址,就是要确定list位于节点中的什么位置(偏置)。上面的宏定义中的`-`号后面的代码就可以实现这个功能 ```c (unsigned long)(&((type *)0)->member)) ``` 分析: `(type *)0` 把一个地址(这个地址的值是0)转化为tpye类型的指针。 再寻址其成员:`((type *)0)->member)` 再取这个成员的地址:`&((type *)0)->member)` 假如定义了一个`struct obj1_node`类型的变量val 假如val的地址是x,那`val.list`取地址肯定是x+4。上面的宏定义就是强行把这里的x置为0,那list成员的地址就是4,直接得到了偏置。 假如现在这们知道list成员的真实地址是ptr,套用宏就是: ```c rt_container_of(ptr, struct obj1_node, list) // 展开 ( (char *)ptr - (unsigned long)( &((struct obj1_node *)0)->list) ) ) ``` 减号后面的结果是4, ptr减去一个4 ,我们就得到了 val 的地址了,近一步可取到其各个成员变量的值了。 rtt中诸多对象--线程、定时器、IPC、设备等的操作--插入、删除、遍历都是通过链表进行管理的。
9
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
Z_Y
这家伙很懒,什么也没写!
文章
11
回答
41
被采纳
1
关注TA
发私信
相关文章
1
链表使用bug:SCB_CFSR_UFSR:0x100 UNALIGNED
2
请教链表代码理解问题
3
关于这个函数 rt_list_insert_before
4
rt-thread使用链表组件编译报错
5
请问有没有介绍rtthread内部链表的材料?
6
单链表问题,rt_slist_for_each 宏问题
7
请问对 rt_slist_t 或 rt_list_t 链表的操作需要加锁吗?
8
IPC 内核链表while()死循环
9
rt_container_of宏接口的使用
10
list_for_each_entry Keil MDK 编译失败,我已经勾选了GUN,依然不行
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部