C 语言中也有很多经典的设计,这些设计被大量的用在软件中。 下面的动态数组的设计比较经典,其实自己也设计过,这次在flex 的源代码中发现这个设计方法,认为是一个可以提炼出来的模式。
实现文件为:
头文件:
#ifndef __BUF_H__
#define __BUF_H__
#include <stdio.h>
struct Buf {
void * elts;
int nelts;
size_t elmsize;
int nmax;
};
void buf_init(struct Buf * , size_t );
void buf_destroy(struct Buf *);
struct Buf* buf_append(struct Buf * , void * , size_t);
#endif
实现文件为:
#include <stdlib.h> #include <string.h> #include "buf.h" /* stub code */ void * allocate_array(int n, size_t es) { register void * mem; size_t cbsize = n * es; mem = malloc(cbsize); if(!mem) { /* fatal error , no memory */ return NULL; } return mem; } void * reallocate_array(void *ptr, int n , size_t es) { register void * mem; size_t cbsize = n * es; mem = (void*)realloc(ptr,cbsize); if(!mem) { /* fatal error, no memory */ return NULL; } return mem; } void flex_free(void *ptr) { if(ptr) { free(ptr); } } void buf_init(struct Buf * buf, size_t size) { buf->elts = NULL; buf->nelts = buf->nmax = 0 ; buf->elmsize = size; } void buf_destroy(struct Buf *buf) { if(buf && buf->elts) { flex_free(buf->elts); buf->elts = NULL; } } struct Buf* buf_append(struct Buf * buf, void * ptr, size_t n) { int cbsize = 0 ; if(!ptr || n == 0) return buf; if( n + buf->nelts > buf->nmax) { cbsize = n + buf->nelts; if(((cbsize * buf->elmsize) % 512 != 0) && buf->elmsize < 512) { cbsize += ( 512 - (cbsize * buf->elmsize) % 512 ) / buf->elmsize; } if(!buf->elts) { buf->elts = allocate_array(cbsize,buf->elmsize); } else { buf->elts = reallocate_array(buf->elts,cbsize,buf->elmsize); } } memcpy((char*) buf->elts + buf->nelts * buf->elmsize , ptr, n * buf->elmsize); buf->nelts += n; return buf; }