如何创建支持多结构体类型的通用动态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
相关产品推荐
相关产品推荐

