Part1一、引入介绍
在阅读华为LiteOS的源码过程中,经常可以看到LOS_DL_LIST_ENTRY这个东东,给它展开其实它就是这样的一个宏定义:
#define LOS_DL_LIST_ENTRY(item, type, member) \
((type *)(VOID *)((CHAR *)(item) - LOS_OFF_SET_OF(type, member)))
这个宏的大题思想就是:结构体的首地址 = 某个成员的地址 - 这个成员的偏移地址。
接下来对这个宏进行完全解读~
Part2二、宏定义解读
首先,先告诉大家它的功能:返回item所在结构体的首地址,也就是这个结构体第一个成员的地址。
再给大家解读下它的三个形参的意义:
item:要查找的结构体所要依据的成员;
type:要查找的结构体的类型;
member:要查找的结构体的类型的某个成员(type中的某个成员);
细节分析
首先看看LOS_OFF_SET_OF:
typedef unsigned int UINTPTR;
#define LOS_OFF_SET_OF(type, member) ((UINTPTR)&((type *)0)->member)
可以看到它也是一个宏定义,
&((type )0)->member:这里我想着重讲解一下,因为实在是太妙了~。先将0强制转换为 (type *)类型的地址,这样((type *)0)->member就表示在以type为结构体类型的member这个成员相对与0这个绝对地址的偏移量了,也就是相对于这个结构体首地址的偏移量,再加个&,即表示member这个成员的偏移地址,在这个地方就等于偏移量,之后再强制转化为无符号整形数据用于地址的加减运算;
(CHAR *)(item):表示将item强制转化为(CHAR *)类型的指针,也就是得到item的地址;讲到这里,下文这段代码的含义我们就能理解了:要查找的结构体所要依据的成员的地址 - member成员相对于这个需要查找的结构体的偏移地址;
(CHAR *)(item) - LOS_OFF_SET_OF(type, member)
最后再将上面这份代码得到的地址强制转化为(type *),那么最终就得到了item所在且为(type *)类型结构体的的首地址,看到这大家是不是终于懂了呢?如若还有疑问欢迎留言~