对C语言有过了解的同学,都知道C语内置了数组类型,可是C数组是静态的—数组的长度在编译时期便已确定了长度(分配了内存)。甚至你都不能这么着使用
const int arr_size = 100; char foo[arr_size];
使用数组即有较高的随机访问特性,但我们在很多实际运用场景都无法预先知道加载数据的长度,却又不舍得一开始就建立一个“巨大”的固定长度的表(数组)。解决这个问题,可以使用链表(参见链表ADT),或者使用动态数组。这里主要介绍一下后者—–动态数组。其基本思路是先使用库函数mallo()分配一块内存,这块内存块连续存放着相应的数据单元,每个单元占用的内存空间是一样大小,然后,像引用数组那样借用指针引用这块内存,通过指针和偏移量可以随机访问各个单元的数据。当这块内存写满的时候,可以调用库函数realloc()重新分配更大空间的内存(函数realloc()不会丢失原来的内存块上的数据)。
我从php源码目录里zend目录扒了一份动态数据源代码,供大家一起学习。(http://lxr.php.net/xref/PHP_5_2/Zend/zend_dynamic_array.c)
/* file:zend_dynamic_arr.h */
#ifndef cstuff_zend_dynamic_arr_h
#define cstuff_zend_dynamic_arr_h
typedef struct _zend_dynamic_array {
    char *array;
    unsigned int element_size;
    unsigned int current;
    unsigned int allocated;
} dynamic_array;
int zend_dynamic_array_init(dynamic_array *darr, unsigned int element_size, unsigned int size);
void *zend_dynamic_array_push(dynamic_array *darr);
void *zend_dynamic_array_pop(dynamic_array *darr);
void *zend_dynamic_array_get(dynamic_array *darr, unsigned int index);
int zend_dynamic_array_destroy(dynamic_array *darr);
int zend_dynamic_array_length(dynamic_array *darr);
#endif
/* @file:zend_dynamic_arr.c */
#include <stdio.h>
#include <stdlib.h>
#include "zend_dynamic_arr.h"
int zend_dynamic_array_init(dynamic_array *darr, unsigned int element_size, unsigned int size) {
    darr->array = (char *)malloc(element_size * size);
    if (darr->array == NULL) {
        fprintf(stderr, "init(), out of memoryn");
        return -1;
    }
    darr->element_size = element_size;
    darr->allocated = size;
    darr->current = 0;
    return 0;
}
void *zend_dynamic_array_push(dynamic_array *darr) {
    if (darr->current >= darr->allocated) {
        darr->allocated *= 2;
        darr->array = (char *)realloc(darr->array, darr->allocated);
        if (!darr->array) {
            fprintf(stderr, "push(), out of memoryn");
            exit(EXIT_FAILURE);
        }
    }
    return (void *)(darr->array + (darr->current++) * darr->element_size);
}
void *zend_dynamic_array_get(dynamic_array *darr, unsigned int index) {
    if (index >= darr->current) {
        fprintf(stderr, "get(), key errorn");
        return NULL;
    }
    return (void *)(darr->array + index * darr->element_size);
}
void *zend_dynamic_array_pop(dynamic_array *darr) {
    if (darr->current > 0) {
        return (void *)(darr->array + (--(darr->current)) * darr->element_size);
    }
    return NULL;
}
int zend_dynamic_array_destroy(dynamic_array *darr) {
    if (!darr->array) {
        free(darr->array);
        darr->current = 0;
        darr->allocated = 0;
    }
    return 0;
}
int zend_dynamic_array_length(dynamic_array *darr) {
    return darr->current;
}
char *zend_dynamic_array_ref(dynamic_array *darr) {
    if (darr->current > 0) {
        return (char *)darr->array[0];
    }
    return NULL;
}
/* @file:zend_dynamic_arr_echo.c */
#include <stdio.h>
#include <stdlib.h>
#include "zend_dynamic_arr.h"
#define INIT_SIZE 1024
int main(int argc, char **argv) {
    dynamic_array buffer;
    char *bp;
    int c;
    if (zend_dynamic_array_init(&buffer, sizeof(char), INIT_SIZE) == -1 ) {
        fprintf(stderr, "init failedn");
        exit(EXIT_FAILURE);
    }
    while ((c = getchar()) != EOF) {
        if ((bp = zend_dynamic_array_push(&buffer)) != NULL) {
            *bp = (char)c;
        }
    }
    bp = zend_dynamic_array_push(&buffer);
    if (bp != NULL) {
        *bp = '