[习题34]C语言:动态数组

使用教材

《“笨办法” 学C语言(Learn C The Hard Way)》
https://www.jianshu.com/p/b0631208a794

  • 完整源码 : liblcthw

https://github.com/zedshaw/liblcthw

  • 源文件路径
    单元测试文件: liblcthw/tests/darray_tests.c
    头文件 : liblcthw/src/lcthw/darray.h
    实现 : liblcthw/src/lcthw/darray.c

代码运行

  • 查看文件目录结构 ls -R
liblcthw$ ls -R
.:
bin  LICENSE  Makefile  README.md  src  tests

./bin:

./src:
lcthw

./src/lcthw:
darray.c  darray.h  dbg.h
  • 执行 make
liblcthw$ make 
(. . . 略 . . .)
Running unit tests:
----
RUNNING: ./tests/darray_tests
ALL TESTS PASSED
Tests run: 8
tests/darray_tests PASS
  • 全部单元测试通过后 再次查看文件结构 ls -R
liblcthw$ ls -R
.:
bin  build  LICENSE  Makefile  README.md  src  tests

./bin:

./build:
liblcthw.a  liblcthw.so

./src:
lcthw

./src/lcthw:
darray.c  darray.h  darray.o  dbg.h

./tests:
darray_tests  darray_tests.c  minunit.h  runtests.sh  tests.log

代码说明

  • 动态数组,是一个void **指针的数组
  • 动态数组DArray
typedef struct DArray {
    int end;
    int max;
    size_t element_size;
    size_t expand_rate;
    void **contents;
} DArray;
  • 关于 static inline

如果你要创建一个宏的代码块,而你又不需要代码生成,那么你就可以使用一个static inline 函数

static inline void *DArray_get(DArray * array, int i)
{
    check(i < array->max, "darray attempt to get past max");
    return array->contents[i];
error:
    return NULL;
}
  • 动态数组,创建
DArray *DArray_create(size_t element_size, size_t initial_max)
{
    DArray *array = malloc(sizeof(DArray));
    check_mem(array);
    array->max = initial_max;
    check(array->max > 0, "You must set an initial_max > 0");
    
    array->contents = calloc(initial_max, sizeof(void *));
    check_mem(array->contents);
    
    array->end = 0;
    array->element_size = element_size;
    array->expand_rate = DEFAULT_EXPAND_RATE;
    
    return array;
    
    error:
        if(array) {
            if(array->contents) free(array->contents);
            free(array);
        }
        return NULL;
}

为结构体申请内存 :DArray *array = malloc(sizeof(DArray));
array->contents = calloc(initial_max, sizeof(void *));

  • 单元测试:测试DArray_create函数
char *test_create()
{
    array = DArray_create(sizeof(int), 100);
    mu_assert(array != NULL, "DArray_create failed.");
    mu_assert(array->contents != NULL, "contents are wrong in darray");
    mu_assert(array->end == 0, "end isn't at the right spot");
    mu_assert(array->element_size == sizeof(int),
            "element size is wrong.");
    mu_assert(array->max == 100, "wrong max length on initial size");

    return NULL;
}
  • 动态数组,调整大小
static inline int DArray_resize(DArray * array, size_t newsize) 
{
    array->max = newsize;
    check(array->max > 0, "The newsize must be > 0.");
    
    void *contents = realloc(array->contents, array->max * sizeof(void *));
    // check contents and assume realloc doesn't  harm the original on error
    
    check_mem(contents);
    
    array->contents = contents;
    
    return 0;
    
    error:
    return -1;
}

void *contents = realloc(array->contents, array->max * sizeof(void *));

malloc calloc realloc

https://zh.cppreference.com/w/c/memory/malloc
malloc
定义于头文件
void* malloc( size_t size );
size - 要分配的字节数
成功时,返回指向新分配内存的指针。为避免内存泄漏,必须用 free() 或 realloc() 解分配返回的指针。
失败时,返回空指针。

https://zh.cppreference.com/w/c/memory/calloc
calloc
定义于头文件
void* calloc( size_t num, size_t size );
num - 对象数目
size - 每个对象的大小
成功时,返回指向新分配内存的指针。为避免内存泄漏,必须用 free() 或 realloc() 解分配返回的指针。
失败时,返回空指针。

https://zh.cppreference.com/w/c/memory/realloc
realloc
定义于头文件
void *realloc( void *ptr, size_t new_size );
ptr - 指向需要重新分配的内存区域的指针
new_size - 数组的新大小(字节数)
成功时,返回指向新分配内存的指针。返回的指针必须用 free() 或 realloc() 归还。原指针 ptr 被非法化,而且任何通过它的访问是未定义行为(即使重分配是就地的)。
失败时,返回空指针。原指针 ptr 保持有效,并需要通过 free() 或 realloc() 归还。

你可能感兴趣的:([习题34]C语言:动态数组)