IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> c语言高级应用 list_entry 链表获取所在结构体的首地址 -> 正文阅读

[数据结构与算法]c语言高级应用 list_entry 链表获取所在结构体的首地址

为了代码简介高效,可以方便的被多个链表连接起来,而且这个链表可以很方便的被各种不同类型数据域复用,我们实现单双链表时候(链表节点中不需要数据域),可以像下面这样子:

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系统内核中的链表就是这样子实现滴喔。

参考文章:

Linux内核链表及list_entry解析_Hugo的博客-CSDN博客_linux list_entry

函数指针及其定义和用法,C语言函数指针详解

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-06 15:30:49  更:2021-12-06 15:32:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:24:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码