评论

收藏

[C++] c语言高级应用 list_entry 链表获取所在结构体的首地址

编程语言 编程语言 发布于:2021-12-07 17:14 | 阅读数:295 | 评论:0

为了代码简介高效,可以方便的被多个链表连接起来,而且这个链表可以很方便的被各种不同类型数据域复用,我们实现单双链表时候(链表节点中不需要数据域),可以像下面这样子:
typedef struct List{  struct List* next;  struct List* pre;  //注:这里面没有数据域}List_t;typedef struct Student{  char name[10];  int age;  int high;  //该学生可能存在于多个链表中,比如在男生链表,又在班级链表  List_t node1;      List_t node2; }Student_t;/***  @fn   ListInsert*  @brief  链表插入新节点*  @param  newNode 新节点*  @param  posNode 插入位置节点*  @return 无*  @note   默认插入到posNode后面*/void ListInsert(List_t* newNode, List_t* posNode){  newNode->pre = posNode;  newNode->next = posNode->next;  posNode->next->pre = newNode;  newNode->next = newNode;}void main(){  Student_t s1,s2;  //s1和s2连接成链表1    ListInsert(&(s1.node1), &(s2.node1));  //s1和s2连接成另一个链表2  ListInsert(&(s1.node2), &(s2.node2));}
此时,当我们得到了s1.node1的地址 (设为p1) 时候,现在想拿到s1的首地址(s1.node1所在结构体),怎么办呢,这时候,过程如下:
1. 获得Student结构体首地址和它的成员node1的地址差,如下
p = &( (Student*)0 -> node1 )    //思想:假设现在Student结构体的首地址假设为0,此时成员node1的地址就是相对偏移啦
2. 拿s1.node1的地址减去得到的地址差即可
p1 - p 就得到了我们想要的Student结构体的首地址。这个就是list_enty宏定义的实现原理,完整实现如下:
#define list_entry(ptr, type, member) \  container_of(ptr, type, member)#define container_of(ptr, type, member) ((type *)((u8*)ptr - offsetof(type,member)))#define offsetof(type, member) ((u32) &((type *)0)->member)
Linux系统内核中的链表就是这样子实现滴喔


关注下面的标签,发现更多相似文章