背景
最近在看《系统程序员成长计划》,里面有个任务是实现一个动态数组,所以我用以前学过的知识实现了一个通用的动态数组,不过暂时只能存放int,char,double,字符串的还没实现。
设计与实现
一.动态数组结构:
struct _Darray
{
void *a;
int length;
int size;
diy_fun expand;
diy_fun append;
diy_fun at;
};
typedef struct _Darray * Darray;
里面有 6 个成员:
1.指针 a 指向动态分配的内存区域,类型为void *,以便存放不同的类型
2.length 存放 a 指向的内存区域的长度
3.size 存放元素的个数
4,5,6都是函数指针,分别用于存放该类型的扩展内存, 添加元素,访问某元素的函数
函数指针diy_fun类型的原型:
typedef void* (*diy_fun) (Darray da, void *x);
二.函数
要使用此动态数组,要有初始化,添加元素,释放数组这3个基本的过程。
为了实现通用类型,初始化我使用了带参数的宏:
#define DARRAY_INIT(TYPE, DA) \
{\
DA = malloc (sizeof (*DA));\
DA->size = 0;\
DA->length = 0;\
DA->expand = D_EXPAND(TYPE);\
DA->append = D_APPEND(TYPE);\
DA->at = D_AT(TYPE);\
DA->a = NULL;\
DA->expand (DA, NULL);\
}
参数 TYPE 就是要存放的类型,DA是 Darray 类型的变量。D_EXPAND(TYPE),D_AAPEND(TYPE),D_AT(TYPE),又是 3 个宏,展开了就是对应类型的扩展内存, 添加元素,访问某元素的函数名。他们的实现是
#define D_EXPAND(TYPE) TYPE##_expand
#define D_APPEND(TYPE) TYPE##_append
#define D_AT(TYPE) TYPE##_at
其中一个为例,D_EXPAND(int) 展开就是int_expend,然后 void *int_expand (Darray da, void *x) 已经在别处定义好了。
回到DARRAY_INIT,这样子只要输入类型和 DA,就可以得到某特定类型的动态数组,其扩展内存, 添加元素,访问某元素的函数也匹配好了
添加元素
添加