ucore lab1,lab2,lab3,lab4链表详解 获取结构体成员偏移

ucore版链表介绍

ucore是清华大学操作系统实验课要完成的操作系统,里面有个链表数据结构我觉得很有意思,记录下来。
ucore将链表与数据对象分离,使得任意数据对象,只要加上一个链表组件就能组织成一个链表。
在这里插入图片描述

要使得一个本来不具有“把自己的对象组织成链表”能力的类型变得有能力组织成链表,只需要

  1. 在定义时多加要给list_entry_t成员.
  2. 定义一个letoxxx的宏,这个宏负责把链表指针转化为对象指针。

从data指针获取下一个data指针的示例

取邻居节点的步骤有三个
第一:取出当前节点的le。
第二:取出当前le 的下一le的地址。
第三:调用le2data,把le指针转化为data指针。
代码如下
假设头节点的指针式head。
那么第二个节点通过下面步骤获取

list_entry_t le=head->le;
list_entry_t* next_le=le.next;
data* next_data=le2data(next_le);

多说几句

这样看链表的使用变得麻烦了。以前我们使用链表都是head->next()->data()。ucore的链表需要3个步骤。
但是链表的开发变得非常简单。对于任意数据结构,只需要加一个list_entry_t成员,然后定义一个le2xxx宏就可以了。而不用给每个数据结构实现next(),prev(),add(),delete()方法。
也许你会想到c++的链表,要把数据组织成链表只需要一行代码:list<data>,就行了。但是这里用到了模板语法。在c语言中没有模板。
c++的链表是包装,它不修改data本来的结构。
ucore的链表是加工,它在data里面加了一点东西,但增加的东西很少,而且丝毫不影响原来的使用。这是在编译器不支持模板情况下非常好的解决方案。

链表实现

le2data 实现获取结构体成员偏移

这里最关键的就是如何把list_entry_t指针le变成data指针。我们知道le是data的一个成员,我们得到le,换个视图看就是这个样子:
在这里插入图片描述
如果把le指针向前偏移offset大小,不就是data指针了吗?
所以问题转化为如何获取offset。
下面,需要比较好的c语言基础,如果看不懂,也没关系,因为这些实现可以cv,直接用就好。
定义一个宏:
在这里插入图片描述
type就是类型,在本语境中,指data。member指类成员,在本语境中指le。
offsetof(struct data,le)的意思就是计算le成员在data中的偏移量。
为了解读方便,我把所有的type替换为data,把所有的member替换为le。

第二行代码解读如下

(data *)0 :我们知道,指针其实就是一个32位的整形。0是32位的整形,所以把0转为了data的指针是允许的。其含义是:内存0号地址开始的若干单元,存放的是一个data类型的对象(虚拟的,实际上并不存在这个对象),我现在用一个没有名字的data指针指向0号地址。既然他是data指针,就一个用->取它的成员数据。

((data *)0->le),取出那个在0号地址的data对象的le成员。

&((data *)0->le),获得那个le成员的地址。这个地址在数值上=offset。因为le的地址=data地址+offset。那么offset=le的地址-data地址=le的地址-0=le的地址。

现在,得到了offset的数值,但编译器此时认为这个数值是个指针,通过(size_t)&((data *)0->le)强制把上一步的指针转化为整形(size_t就是无符号整形)。

le2data的整体实现

通过3个宏
在这里插入图片描述在这里插入图片描述
实际上,我们要实现le2xxx,只需要改一个红色框框住的那部分就行。

链表操作的实现

增加,删除,这些操作就是普通的链表操作,实现也是基本 一致,就不详细展开了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值