#define LOS_DL_LIST_ENTRY(item, type, member) ((type *)((char *)item - LOS_OFF_SET_OF(type, member)))
首先来确定LOS_OFF_SET_OF是什么
#define LOS_OFF_SET_OF(type, member) ((long)&((type *)0)->member)
把类型强制转换为0,然后取成员member的地址。最后在转换为long。
问题来了,为什么要转换为0?
因为这里是计算member针对这个类型的偏移地址,转换为0之后,直接可以得到member的偏移地址。
#define LOS_DL_LIST_ENTRY(item, type, member)
((type *)((char *)item - LOS_OFF_SET_OF(type, member)))
这里是计算类型的首地址。对于结构体来说,这个结构体的地址就是成员的首地址
举例:osTaskScan函数
for (pstTaskCB = LOS_DL_LIST_ENTRY((pstListObject)->pstNext, LOS_TASK_CB, stTimerList);&pstTaskCB->stTimerList != (pstListObject);)
其中 item = (pstListObject)->pstNext;
type = LOS_TASK_CB;
member = stTimerList;
typedef struct tagTaskCB
{
VOID *pStackPointer; /**< Task stack pointer */
UINT16 usTaskStatus;
.....
LOS_DL_LIST stTimerList;
VOID *puwMsg; /**< Memory allocated to queues */
} LOS_TASK_CB;
通过 LOS_OFF_SET_OF可以计算出 stTimerList到pStackPointer的偏移量
pstListObject->pstNext经过宏转换得到一个地址,这个地址就是member的地址,然后减去member的偏移量,就是结构体的首地址了