当前位置: 首页 > news >正文

FreeRTOS---进阶知识4---通用链表

在之前的链表操作中可以看到,在创建struct person结构体时,其结构体成员和指针是放在同一个结构体中:

struct person {char *name;int age;struct person *next;  // 数据和指针耦合
};

下面以添加链表操作为例,介绍上面代码的局限性:

struct person{char *name;int age;struct person *next;/*指向下一个人*/
};struct list{char *name;/*列表名称*/struct person head;/*指向某个人*/
};void InitList(struct list *pList,char *name)
{pList ->name = name ;pList ->head.next = NULL ;
}void AddItemToList(struct list *pList,struct person *new_person)
{struct person *last = &pList->head;while (last->next){last = last->next;}last->next = new_person;new_person->next = NULL;
}

上面的代码本身是改进过链表的定义内容,但是如果需要将其他类型的结构体添加进链表时,就会出现代码冗余的问题。

比如,需要重新定义结构体 struct bird{  },将 struct bird{  }也添加进链表,那么就需要重新写个代码  Void   AddItemToList(struct list *pList,struct bird  *new_bird),当有多个结构体类型时,都要写一个新的函数。这显然是有问题的。

下面,将介绍通用链表操作,也就是说不管结构体的类型如何,只需要一个函数Void   AddItemToList()即可

具体代码如下:

struct node_t{struct node_t *next;
}struct person{char *name;int age;struct node_t node;
};struct list{char *name;/*列表名称*/struct node_t head;
};void InitList(struct list *pList,char *name)
{pList ->name = name ;pList ->head.next = NULL ;
}void AddItemToList(struct list *pList,struct node_t *new_node)
{struct node_t *last = &pList->head;while (last->next){last = last->next;}last->next = new_node;new_node->next = NULL;
}

实际内存结构

两个person实例:

person1 实例
+-------------+
| name:"张三" | ← 数据
+-------------+
| age:18      | ← 数据
+-------------+
| node.next   | → 指向person2的node ← 连接环
+-------------+person2 实例  
+-------------+
| name:"李四" | ← 数据
+-------------+
| age:20      | ← 数据
+-------------+
| node.next   | → NULL ← 连接环
+-------------+

链表连接关系:

list.head
+----------+
| next     | → 指向person1的node
+----------+person1.node
+----------+
| next     | → 指向person2的node  
+----------+person2.node
+----------+
| next     | → NULL
+----------+

如何从连接环找到数据?

问题:

我们知道node的地址,如何找到包含它的person

解决方案:计算偏移量

// 方法1:使用offsetof宏
struct person* node_to_person(struct node_t *node)
{return (struct person*)((char*)node - offsetof(struct person, node));
}// 方法2:假设node在person中的位置
struct person* node_to_person(struct node_t *node)
{return (struct person*)((char*)node - 8); // 假设name和age共占8字节
}

完整使用示例

1. 创建数据节点

struct person p1 = {"张三", 18, {NULL}};
struct person p2 = {"李四", 20, {NULL}};

2. 初始化链表

struct list my_list;
InitList(&my_list, "班级列表");

3. 添加节点

AddItemToList(&my_list, &p1.node); // 传递node的地址
AddItemToList(&my_list, &p2.node); // 传递node的地址

4. 遍历链表

void PrintList(struct list *pList)
{// 从头节点的第一个连接环开始struct node_t *current = pList->head.next;while (current != NULL) {// 从连接环找到包含它的personstruct person *p = (struct person*)((char*)current - 8);printf("姓名: %s, 年龄: %d\n", p->name, p->age);// 移动到下一个连接环current = current->next;}
}

http://www.dtcms.com/a/531818.html

相关文章:

  • jvm逃逸问题的分析以及给出解决方案?
  • PHP 表单:深入浅出地掌握表单处理
  • Linux(Ubuntu)操作系统下文件的解压
  • HTTP 1.0版本的webserver自主实现
  • 【开题答辩全过程】以 基于微信小程序的个性化饮品定制点餐系统设计与实现为例,包含答辩的问题和答案
  • kotlin - 显示heic图片
  • 做网站域名是什么意思网站不备案会怎样
  • A2A+MCP构建智能体协作生态:下一代分布式人工智能架构解析
  • SpringBoot 的三类配置文件
  • 创造模式物品栏——多物品栏
  • Docker中部署多个ASP.NET Core实例
  • HarmonyOS生物识别认证深度解析:从指纹到人脸的安全实践
  • GitHub等平台形成的开源文化正在重塑加热d
  • C++新特性概览
  • dify 配置 deepseek Credentials validation failed with status code 402
  • 【自然语言处理】Transformer模型
  • 使用 RapidXML 实现 C++ 中的 XML 文件读取与生成,特别适合需要快速处理 XML 的场景
  • 基于Reactor模式的高性能C++仿Muduo库:Server服务器模块实现
  • 常州市网站建设设计公众号开发和小程序开发哪个简单
  • 【Android】DrawerLayout实现侧边导航栏
  • 缓存查询逻辑及问题解决
  • 襄阳网站seo公司江津网站建设口碑
  • 【中望3D 2025】配置【vs2022】开发环境
  • 基于定制开发开源AI智能名片S2B2C商城小程序的全方位种草模式研究
  • 实现Callable接口(了解即可)
  • 从入门到实操:贝叶斯分析完整技术步骤与核心R包指南
  • 做理财的网站有哪些内容长春一般建一个网站需要多少钱
  • C#开发后端:API 控制器(Controller)
  • 建湖人才网招工湛江怎么做网站关键词优化
  • 深入理解 Flink SQL 状态:原理、应用与优化