You need to enable JavaScript to run this app. C语言通用队列实现:能否脱离外部地址存储任意数据类型对象?
优惠活动
大模型
产品
解决方案
定价
更多

C语言通用队列实现:能否脱离外部地址存储任意数据类型对象?

泛型队列独立持有任意类型数据的实现方案

你当前实现的泛型队列存在的核心问题是:节点仅存储了外部传入的指针地址,没有对指针指向的数据做独立拷贝。一旦外部对应内存的内容被修改、或者内存被回收,队列中存储的引用就会失效,无法满足队列自管理数据的设计目标。

C语言是静态类型语言,运行时无法自动识别传入数据的类型和大小,要实现队列内部存储数据实体本身,只需要在队列操作接口中显式传入待存储数据的字节长度,队列内部就可以根据长度申请对应大小的堆内存,把外部传入的数据完整拷贝到队列自有的内存空间,彻底和外部内存解耦。

结构与接口调整

  • 队列节点新增两个字段:一个指向队列自有存储内存的void*指针,一个记录当前存储数据长度的size_t变量,方便后续内存管理
  • 修改enqueue接口入参,新增待存储数据的字节长度参数,替代原来仅接收外部指针的设计
  • 入队流程中,单独为每个节点的存储内容申请对应长度的堆内存,通过memcpy完成数据的独立拷贝

调整后的完整可运行代码

#include <stdlib.h>
#include <string.h>

typedef struct Node {
    void *data_storage; // 队列专属的数据存储内存
    size_t data_size;   // 记录存储数据的字节长度,用于内存管理
    struct Node *next;
} Node;

typedef struct Queue {
    Node *front;
    Node *back;
} Queue;

Queue* initializeQueue() {
    Queue *queue = (Queue*)malloc(sizeof(Queue));
    // 增加内存申请失败的边界判断
    if (queue == NULL) return NULL;
    queue->front = NULL;
    queue->back = NULL;
    return queue;
}

void enqueue(Queue *queue, const void *data, size_t data_size) {
    // 边界参数校验
    if (queue == NULL || data == NULL || data_size == 0) return;

    // 申请新节点内存
    Node *new_node = (Node*)malloc(sizeof(Node));
    if (new_node == NULL) return;

    // 为节点申请和待存数据等长的专属存储内存
    new_node->data_storage = malloc(data_size);
    if (new_node->data_storage == NULL) {
        free(new_node);
        return;
    }

    // 把外部传入的数据完整拷贝到队列自有内存,和外部内存脱钩
    memcpy(new_node->data_storage, data, data_size);
    new_node->data_size = data_size;
    new_node->next = NULL;

    // 原有入队逻辑保持不变
    if (queue->front == NULL) {
        queue->front = new_node;
        queue->back = new_node;
    } else {
        queue->back->next = new_node;
        queue->back = new_node;
    }
}

效果验证

使用之前提到的char变量入队的场景,调用方式调整为:

char key = '-';
// 显式告知队列当前数据的长度为char类型的字节大小
enqueue(queue, &key, sizeof(char));

入队完成后,无论外部的key变量是被修改值、还是离开作用域被回收,队列内部存储的都是独立拷贝的完整数据,不会出现悬空引用问题。这套方案同样兼容int、结构体、字符串等任意数据类型的存储。

配套注意事项

  • 实现出队和队列销毁逻辑时,需要先释放每个节点对应的data_storage内存,再释放节点本身,避免内存泄漏
  • 入队时会对传入数据做一次完整的字节拷贝,如果存储的是体积较大的结构体,需要根据实际场景权衡拷贝开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.12 20:54:01