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

如何创建支持多结构体类型的通用动态C数组?

如何创建兼容多结构体类型的动态C数组?

我需要实现一个能适配任意数据类型的动态C数组,具体场景里要让dynamicArr同时兼容struct1和struct2两种结构体。请问定义中的structuretype应该设置成什么类型才能满足需求?

相关代码定义如下:

typedef struct dynamicArr
{
    structuretype *arr;
    int capacity;
    int size;
}dynamicArr;
typedef struct struct1
{
    int id;
    char *field1;
    char *field2;
    int num;
}struct1;
typedef struct struct2
{
    char *field;
    int num1;
    int num2;
}struct2;

解决方案:使用void*作为通用指针类型

在C语言中,要实现通用动态数组,核心是用void*(无类型指针)作为数组的存储指针——void*可以指向任意数据类型的内存地址,天然具备通用性。不过仅替换指针类型还不够,还需要补充元素大小的记录,才能正确进行内存分配和元素操作。

1. 修改动态数组结构体定义

把structuretype*替换为void*,并新增elem_size字段存储单个元素的字节大小:

typedef struct dynamicArr
{
    void *arr;          // 通用指针,指向任意类型的元素数组
    size_t elem_size;   // 单个元素的字节大小
    int capacity;       // 数组总容量
    int size;           // 当前已存储元素数量
} dynamicArr;

2. 实现核心操作函数

初始化动态数组

需要传入元素大小和初始容量,才能正确分配内存:

dynamicArr* da_create(size_t elem_size, int initial_capacity) {
    dynamicArr *da = malloc(sizeof(dynamicArr));
    if (!da) return NULL;
    
    da->elem_size = elem_size;
    da->capacity = initial_capacity > 0 ? initial_capacity : 4; // 默认初始容量4
    da->size = 0;
    da->arr = malloc(da->capacity * da->elem_size);
    if (!da->arr) {
        free(da);
        return NULL;
    }
    return da;
}

添加元素

因为void*不能直接解引用赋值,需要用memcpy将元素数据复制到数组中,同时自动扩容:

int da_add(dynamicArr *da, const void *elem) {
    if (!da || !elem) return -1;
    
    // 容量不足时扩容(通常扩容为原容量的2倍)
    if (da->size >= da->capacity) {
        int new_capacity = da->capacity * 2;
        void *new_arr = realloc(da->arr, new_capacity * da->elem_size);
        if (!new_arr) return -1;
        da->arr = new_arr;
        da->capacity = new_capacity;
    }
    
    // 计算目标位置并复制元素
    char *target = (char*)da->arr + da->size * da->elem_size;
    memcpy(target, elem, da->elem_size);
    da->size++;
    return 0;
}

获取元素

需要将void*转换为对应结构体类型的指针,注意要通过char*计算偏移量(void*不支持算术运算):

// 获取struct1类型元素
struct1* da_get_struct1(dynamicArr *da, int index) {
    if (!da || index < 0 || index >= da->size) return NULL;
    return (struct1*)((char*)da->arr + index * da->elem_size);
}

// 获取struct2类型元素
struct2* da_get_struct2(dynamicArr *da, int index) {
    if (!da || index < 0 || index >= da->size) return NULL;
    return (struct2*)((char*)da->arr + index * da->elem_size);
}

销毁动态数组

注意要先释放结构体内部的堆内存(比如struct1中的field1、field2),再释放数组本身和动态数组结构体:

void da_destroy_struct1(dynamicArr *da) {
    if (!da) return;
    // 释放每个struct1内部的字符串
    for (int i = 0; i < da->size; i++) {
        struct1 *s = da_get_struct1(da, i);
        free(s->field1);
        free(s->field2);
    }
    free(da->arr);
    free(da);
}

void da_destroy_struct2(dynamicArr *da) {
    if (!da) return;
    // 释放每个struct2内部的字符串
    for (int i = 0; i < da->size; i++) {
        struct2 *s = da_get_struct2(da, i);
        free(s->field);
    }
    free(da->arr);
    free(da);
}

3. 使用示例

// 创建存储struct1的动态数组
dynamicArr *da1 = da_create(sizeof(struct1), 4);
if (da1) {
    struct1 s1 = {1, strdup("hello"), strdup("world"), 100};
    da_add(da1, &s1);
    // 获取并使用元素
    struct1 *get_s1 = da_get_struct1(da1, 0);
    printf("struct1 id: %d, field1: %s\n", get_s1->id, get_s1->field1);
    da_destroy_struct1(da1);
}

// 创建存储struct2的动态数组
dynamicArr *da2 = da_create(sizeof(struct2), 4);
if (da2) {
    struct2 s2 = {strdup("test"), 200, 300};
    da_add(da2, &s2);
    struct2 *get_s2 = da_get_struct2(da2, 0);
    printf("struct2 num1: %d, num2: %d\n", get_s2->num1, get_s2->num2);
    da_destroy_struct2(da2);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:05:32