zend php 动态数组

对C语言有过了解的同学,都知道C语内置了数组类型,可是C数组是静态的—数组的长度在编译时期便已确定了长度(分配了内存)。甚至你都不能这么着

对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 memory/n");

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 memory/n");

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 error/n");

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 failed/n");

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 = '/0';

}

bp = zend_dynamic_array_get(&buffer, 0);

if (bp != NULL) {printf("%s", bp);

zend_dynamic_array_destroy(&buffer);

}

return 0;

}

/* @file:Makefile_ZDarray */

echo_darr:zend_dynamic_arr.o zend_dynamic_arr_echo.c

cc -o echo_darr zend_dynamic_arr.o zend_dynamic_arr_echo.c

zend_dynamic_arr.o:zend_dynamic_arr.h

clean:

-rm -f echo_zd_array zend_dynamic_arr.o

我们可以另外用一个例程(使用数组)对比,参见代码如下:

#include <stdio.h>

#define MAX_SIZE 1024

int main(int argc, char **argv) {

char buffer[MAX_SIZE];

int i, c, limit;

i = 0, limit = MAX_SIZE;

while (--limit > 0 && (c = getchar()) != EOF) {

buffer[i++] = (char)c;

}

if (i > 0) {

buffer[i] = '/0';printf("%s", buffer);

}

return 0;

}

最后,我们可以看看两个例程(echo_arr和echo_darr)输出对比,可以看到dynamic array和array的应用场景会不同。

ryoumatoMacBook-Pro:cstuff 3river$ cat linklist.c |./echo_darr |wc -c

3755

ryoumatoMacBook-Pro:cstuff 3river$ cat linklist.c |./echo_arr |wc -c

1023

ryoumatoMacBook-Pro:cstuff 3river$ cat linklist.c |wc -c

3755

未登录用户
全部评论0
到底啦