84.单片机动态缓存利器:单向链表原理与可运行实战代码

一、单向链表的核心原理

单向链表是一种链式存储结构,每个节点包含两部分:

  • 数据域:存储实际的数据(比如整数、结构体)
  • 指针域:存储下一个节点的地址,形成“链”的结构
头节点 → 节点1 → 节点2 → 节点3 → NULL

1. 节点结构定义

在C语言中,我们用struct定义链表节点:

#include <stdio.h>
#include <stdlib.h>

// 链表节点结构
typedef struct Node {
    int num;           // 数据域:存储整数
    struct Node *next; // 指针域:指向next节点
} Node;

2. 链表的优势

  • 动态内存分配:需要多少节点就分配多少,不浪费RAM
  • 插入/删除高效:不需要移动大量数据,只需要修改指针
  • 长度可变:可以随时添加或删除节点,适配变长数据

二、单向链表的基本操作

1. 创建新节点

// 创建新节点
Node* NewNode(int num) {
    Node *node = (Node*)malloc(sizeof(Node)); // 分配内存
    if (node == NULL) {
        printf("内存分配失败!\n");
        return NULL;
    }
    node->num = num;       // 赋值数据
    node->next = NULL;     // 初始化为空指针
    return node;
}

2. 头插法:在链表头部插入节点

// 头插法:在链表头部插入新节点
void Add(Node **head, int v) {
    Node *newNode = NewNode(v);
    if (newNode == NULL) return;
    
    newNode->next = *head; // 新节点的next指向原头节点
    *head = newNode;       // 更新头节点为新节点
}

3. 遍历链表:打印所有节点数据

// 遍历链表:打印所有节点数据
void Show(Node *head) {
    Node *p = head;
    while (p != NULL) {
        printf("%d ", p->num);
        p = p->next; // 移动到下一个节点
    }
    printf("\n");
}

4. 释放链表:释放所有节点内存

// 释放链表:释放所有节点内存
void FreeList(Node **head) {
    Node *p = *head;
    while (p != NULL) {
        Node *temp = p;
        p = p->next;
        free(temp); // 释放当前节点
    }
    *head = NULL; // 头节点置空
}

三、完整可运行示例

int main() {
    Node *head = NULL; // 头节点初始化为空
    
    // 插入节点
    Add(&head, 33);
    Add(&head, 22);
    Add(&head, 11);
    
    printf("链表数据:");
    Show(head); // 输出:11 22 33
    
    // 释放链表
    FreeList(&head);
    return 0;
}

运行结果

链表数据:11 22 33

四、单片机中的实战应用

在单片机中,我们可以用单向链表实现串口变长数据缓存

// 串口数据节点
typedef struct UartData {
    uint8_t len;        // 数据长度
    uint8_t buf[64];    // 数据缓冲区
    struct UartData *next;
} UartData;

// 串口接收回调函数(示例)
UartData *uartHead = NULL;

void UART_RxHandler(uint8_t data) {
    static UartData *currentNode = NULL;
    static uint8_t index = 0;
    
    // 假设帧头为0xAA,帧尾为0x55
    if (data == 0xAA) {
        // 新帧开始,创建新节点
        currentNode = (UartData*)malloc(sizeof(UartData));
        if (currentNode == NULL) return;
        currentNode->len = 0;
        currentNode->next = NULL;
        index = 0;
    } else if (data == 0x55 && currentNode != NULL) {
        // 帧结束,将节点加入链表
        currentNode->len = index;
        currentNode->next = uartHead;
        uartHead = currentNode;
        currentNode = NULL;
    } else if (currentNode != NULL) {
        // 存储数据
        currentNode->buf[index++] = data;
        if (index >= 64) {
            // 缓冲区满,丢弃当前帧
            free(currentNode);
            currentNode = NULL;
        }
    }
}

五、注意事项

  1. 内存分配失败:单片机RAM有限,malloc可能失败,必须判断返回值
  2. 内存泄漏:必须调用free释放不再使用的节点
  3. 指针操作:操作指针时要注意空指针,避免程序崩溃
  4. 中断安全:在中断中操作链表时,要关中断保护临界区

六、总结

单向链表是单片机中处理动态数据的必备工具,它的核心优势是动态内存分配高效插入/删除。通过本文的代码示例,你可以快速在单片机项目中实现变长数据缓存,比如串口数据包、传感器数据采集等场景。

在实际开发中,你还可以扩展链表功能,比如实现尾插法、查找节点、删除指定节点等,以满足更多需求。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值