You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于void结构体的链表如何实现节点链接?附示例代码

实现基于void*的链表节点链接

我来帮你搞定这个问题——用void实现链表节点链接的核心难点,就是如何通过无类型指针访问节点的next成员,毕竟void本身没法直接解引用结构体成员。结合你给出的代码片段,我给你补全实现并解释清楚思路:

先明确你的链表节点结构

首先我假设你已经定义了struct tmpList(毕竟你的addToken2TmpList里在用它),它应该长这样:

struct tmpList {
    char *data;
    struct tmpList *next;
};

你的cocatenateNodes用void做参数,本质是想做一个通用的节点拼接函数,但要让它能工作,我们得先明确:传入的void指针,实际指向的都是struct tmpList类型的节点(或者其他有相同next成员结构的节点)。

补全并修正cocatenateNodes函数

你写了函数的开头,下面是完整的可运行实现:

void *cocatenateNodes(void *node, void *headNode) {
    // 把void*转成具体的节点类型指针,才能访问next成员
    struct tmpList *tmpHead = (struct tmpList *)headNode;
    struct tmpList *newNode = (struct tmpList *)node;

    if (headNode == NULL) {
        // 链表为空的话,新节点直接当表头
        return node;
    } else {
        // 遍历到链表的最后一个节点
        while (tmpHead->next != NULL) {
            tmpHead = tmpHead->next;
        }
        // 把新节点挂到链表尾部
        tmpHead->next = newNode;
        // 返回原来的表头(因为表头没变化)
        return headNode;
    }
}

这里的关键是类型转换:把void*转成struct tmpList*,这样就能正常访问next指针了。

进阶:做真正通用的void*链表(不依赖具体结构体)

如果你想让cocatenateNodes完全不绑定struct tmpList,可以用“嵌入通用节点头部”的技巧,让它能处理任意链表节点:

// 定义一个通用的链表节点头部,只包含next指针
struct GenericListNode {
    struct GenericListNode *next;
};

// 你的具体节点结构体,把通用头部嵌在最前面
struct tmpList {
    struct GenericListNode node;
    char *data;
};

然后cocatenateNodes可以改成完全通用的版本:

void *cocatenateNodes(void *node, void *headNode) {
    struct GenericListNode *genNode = (struct GenericListNode *)node;
    struct GenericListNode *genHead = (struct GenericListNode *)headNode;

    genNode->next = NULL; // 确保新节点的next是空的,避免乱指

    if (genHead == NULL) {
        return node;
    }

    // 遍历到链表尾部
    while (genHead->next != NULL) {
        genHead = genHead->next;
    }
    genHead->next = genNode;
    return headNode;
}

这种方式下,任何嵌入了struct GenericListNode的结构体,都可以用这个函数来拼接,真正实现了通用的链表操作。

对你现有代码的小提醒

在你的addToken2TmpList里,直接把token赋值给tokenNode->data可能会有问题——如果token是栈上的临时字符串,函数返回后这个指针就变成野指针了。建议用strdup复制一份字符串:

struct tmpList *addToken2TmpList(struct tmpList *headTmpList, char *token) {
    struct tmpList *tokenNode = (struct tmpList *)malloc(sizeof(struct tmpList));
    tokenNode->data = strdup(token); // 复制字符串到堆上,避免野指针
    tokenNode->next = NULL;
    return (struct tmpList *)cocatenateNodes(tokenNode, headTmpList);
}

记得最后释放链表的时候,要先释放data指向的内存,再释放节点本身哦。


内容的提问来源于stack exchange,提问作者FelX3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:02:59