C语言应用笔记:巧妙使用链表分时处理多个任务
在C语言中,链表是一种常用的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。利用这些特性,结合函数指针设计多任务系统,可有效缩短多个任务一起执行带来的时间开销。下面是一个简单示例:
具备链表特性的结构体变量定义
typedef struct test_list {
uint8_t id; // 用于标识任务编号
void (*func)(void); // 用于存放任务地址
struct test_list *next; // 指向下一个将要执行的节点
} TestList;
定义一个结构体变量,它包含了三个成员:
- id: 用于标识任务的编号
- func: 一个函数指针,指向一个无返回值、无参数的函数。这是实现“任务”的关键
- next: 一个指向相同结构体类型的指针。这是构成链表的基础,它用于指向下一个节点
链表的创建与连接
static void foo1(void) {
printf("这是函数1\r\n");
delay(0xFF);
}
static void foo2(void) {
printf("这是函数2\r\n");
delay(0xFF);
}
static void foo3(void) {
printf("这是函数3\r\n");
delay(0xFF);
}
// 定义任务链表,首尾相连,保证能循环执行
static TestList my_list[] = {
{.id = 0, .func = foo1, &my_list[1]},
{.id = 1, .func = foo2, &my_list[2]},
{.id = 2, .func = foo3, &my_list[0]},
};
在程序编译链接后,这个数组的每个元素的地址就固定了。通过直接在初始化器中使用 &my_list[1] 这样的地址来设置 next 指针,人工地将三个节点连接起来。特别地,最后一个节点指向了第一个节点,从而构成了一个循环链表。
链表遍历与任务执行
int main(void) {
// 创建指针,指向链表头(第一个节点)
TestList *ptr_list = &my_list[0];
uint32_t count = 5;
printf("程序开始运行...\r\n");
do {
// 执行当前节点指向的函数
ptr_list->func();
// 指针移动到下一个节点
ptr_list = ptr_list->next;
} while (count--);
return 0;
}
这个过程清晰地演示了链表的遍历:通过 next 指针,可以一个接一个地访问链表中的每一个节点,无需使用数组索引。由于是循环链表,当指针移动到最后一个节点后,next 会再次指向第一个节点,可以无限循环下去(本例中由 count 变量控制循环次数)。
输出结果
程序开始运行...
这是函数1
这是函数2
这是函数3
这是函数1
这是函数2
这是函数3
相关文章
- Spring Boot中对接Twilio以实现发送验证码和验证短信码
- Spring Boot 3.5:这次更新让你连配置都不用写了,惊不惊喜?
- Spring Boot+Pinot实战:毫秒级实时竞价系统构建
- SpringBoot敏感配置项加密与解密实战
- SpringBoot 注解最全详解,建议收藏!
- Spring Boot 常用注解大全:从入门到进阶
- SpringBoot启动之谜:@SpringBootApplication如何让配置化繁为简
- Springboot集成Kafka原理_spring集成kafka的原理
- Spring Boot中@Data注解的深度解析与实战应用
- 大佬用1000字就把SpringBoot的配置文件讲的明明白白!