起因
工作很少接触纯C项目,业余写着玩玩,不断雕琢
目标
纯C实现动态数组,提供方便易用泛型接口,避免依赖
实现
完全封装,隐藏结构体细节,不支持栈创建
拷贝存储,轻微性能代价换来易用性
vector.h
#ifndef VECTOR_H
#define VECTOR_H
#include <stddef.h>
typedef struct Vector_ Vector;
extern Vector* vector_new(size_t elem_size);
extern void vector_free(Vector* v);
extern size_t vector_length(Vector* v);
extern void vector_get(Vector* v, size_t pos, void* elem_out);
extern void vector_set(Vector* v, size_t pos, void* elem_in);
extern int vector_append(Vector* v, void* elem_in); // On failure, returns -1.
#endif // VECTOR_H
vector.c
#include "vector.h"
#include <stdlib.h>
#include <string.h>
typedef unsigned char byte;
typedef struct Vector_ {
size_t count;
size_t max_count;
size_t elem_size;
byte* data;
} Vector;
#define vector_max_size(v) ((v->elem_size)*(v->max_count))
Vector* vector_new(size_t elem_size) {
Vector* v = calloc(1, sizeof(Vector));
if (v) v->elem_size = elem_size;
return v;
}
void vector_free(Vector* v) {
if(v->data) free(v->data);
free(v);
}
size_t vector_length(Vector* v) {
return v->count;
}
void vector_get(Vector* v, size_t pos, void* elem_out) {
if (pos < v->count) {
byte* p = v->data + v->elem_size * pos;
memcpy(elem_out, p, v->elem_size);
}
}
void vector_set(Vector* v, size_t pos, void* elem_in) {
if (pos < v->count) {
byte* p = v->data + v->elem_size * pos;
memcpy(p, elem_in, v->elem_size);
}
}
int vector_append(Vector* v, void* elem_in) {
if (v->count >= v->max_count) {
byte* data;
v->max_count = (v->max_count)?(v->max_count*2):(4);
data = realloc(v->data, vector_max_size(v));
if (!data) return -1;
v->data = data;
}
vector_set(v, v->count++, elem_in);
return 0;
}
测试
#include <stdio.h>
#include <stdlib.h>
#include "vector.h"
int main(int argc, char *argv[]) {
Vector* v = vector_new(sizeof(int));
size_t v_len = 0;
int i, x, y;
for (i=0; i<10; i++) {
vector_append(v, &i);
}
v_len = vector_length(v);
printf("v_len:%d
", v_len);
for (i=0; i<v_len; i++) {
vector_get(v, i, &x);
printf("%d:%d ", i, x);
x *= 100;
vector_set(v, i, &x);
vector_get(v, i, &y);
printf("%d:%d
", i, y);
}
vector_free(v);
return 0;
}
v_len:10
0:0 0:0
1:1 1:100
2:2 2:200
3:3 3:300
4:4 4:400
5:5 5:500
6:6 6:600
7:7 7:700
8:8 8:800
9:9 9:900