读书笔记 ——《系统程序员成长计划》篇7:动态数组

说明
  本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
  QQ 群 号:513683159 【相互学习】
内容来源
  《系统程序员成长计划》、C语言实现动态数组,克服静态数组大小固定的缺陷

上一篇:读书笔记 ——《系统程序员成长计划》篇6:写的又快又好的秘诀
下一篇:读书笔记 ——《系统程序员成长计划》篇8:排序算法

一、概念

1、什么是动态数组?

  C语言中,数组长度必须在创建时指定,且只能是常数不能是变量。定义后系统将为它分配固定大小的空间,以后不能改变,称为静态数组。但在编程过程中,有时所需的内存空间无法预先确定,故用静态数组的办法很难解决。
  动态数组可随程序需要而重新指定大小。通过执行代码在内存空间从堆(heap)上分配(即动态分配)的。当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。

2、双向链表和动态数组的对比

情形 动态数组 双向链表
空间占用情况 占用一块连续的内存 每个结点占用一块内存
频繁增删数据 需移动后面元素 只需修改前后元素指针,但容易造成内存碎片
是否支持多种高效排序算法 支持,如:快速排序、归并排序,堆排序等 表现不好,甚至不如冒泡排序
排序好的数据 可使用二分查找 仍只能用顺序查找
小量数据 区别不大 区别不大

二、动态数据的实现

  同样选择存指针,故实现的是指针数组。

1、简单实现

#include <stdio.h>
#include <stdlib.h>
int main(){
    int arrLen;  // 数组长度
    int *array;  // 数组指针
    int i;  // 数组下标
    printf("输入数组长度:");
    scanf("%d", &arrLen);
    // 动态分配内存空间,如果失败就退出程序
    array = (int*)malloc( arrLen*sizeof(int) );
    if(!array)
    {
        printf("创建数组失败!\n");
        exit(1); 
    }
    // 向内存中写入数据
    for(i=0; i<arrLen; i++)
    {
        array[i] = i+1;
    } 
    // 循环输出数组元素
    for(i=0; i<arrLen; i++)
    {
        printf("%d  ", array[i]);
    }
    printf("\n");
    free(array);  
    return 0;
}

实现现象:

输入数组长度:20
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20 

  这边定义了数组指针,指向malloc函数创建的一整块内存空间,实现动态数组,动态输入数组长度后自动赋值数据并输出。实际上与静态数组并没有什么区别。

2、书中示例 关键函数简述

(1)动态数组 结构体
struct _DArray;				
typedef struct _DArray DArray;
typedef void     (*DataDestroyFunc)(void* ctx, void* data);

struct _DArray
{
	void** data;										//数据
	size_t size;										//实际使用大小
	size_t alloc_size;									//分配空间大小
	void* data_destroy_ctx;								//销毁函数中上下文数据
	DataDestroyFunc data_destroy;						//函数指针,为指向销毁函数
};
(2)动态数组 创建函数
/**
 * @function:动态数组 创建函数
 * 
 * @param data_destroy: 使用者编写的销毁函数的函数指针
 * @param ctx: 			销毁函数中的上下文数据
 * 
 * @return:				指向该动态数组地址
 * @description:
 * 		开辟一块动态数组结构体大小的空间,并赋初始值。
*/
DArray* darray_create(DataDestroyFunc data_destroy, void* ctx)
{
	DArray* thiz = malloc(sizeof(DArray));						//分配空间

	if(thiz != NULL)											//若成功分配则对结构体变量初始化
	{
		thiz->data  = NULL;
		thiz->size  = 0;
		thiz->alloc_size = 0;
		thiz->data_destroy = data_destroy;
		thiz->data_destroy_ctx = ctx;
	}

	return thiz;
}
(3)动态数组 扩展函数
/**
 * @function:动态数组 扩展函数
 * 
 * @param thiz:			指向动态数组
 * @param need:			所需动态数组大小
 * 
 * @return:				运行状态
 * @description:
 * 	扩展数组时,并不是一次扩展一个元素,而是多个元素,1.5倍为作者的经验所得
*/
#define MIN_PRE_ALLOCATE_NR 10
static Ret darray_expand(DArray* thiz, size_t need)
{
	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); 		//若不存在则直接返回错误

	if((thiz->size + need) > thiz->alloc_size)					//若现用大小+所需大小 > 现有实际大小
	{
		size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;//扩大为原来的1.5倍并加上常数

		void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);				//重新分配大小
		if(data != NULL)
		{
			thiz->data = data;
			thiz->alloc_size = alloc_size;
		}
	}

	return ((thiz->size + need) <= thiz->alloc_size) ? RET_OK : RET_FAIL;					//判断是否执行成功
}

①函数简介
  realloc()函数:尝试重新调整之前调用 malloc calloc 所分配的ptr所指向的内存块的大小
  函数原型void *realloc(void *ptr, size_t size)
  参数
    1️⃣ ptr – 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloccallocrealloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。
    2️⃣ size – 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。
  返回值
    该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

②扩展1.5倍的公式size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;
  为什么要用这个公式呢
    大多数嵌入式平台并不支持硬件浮点数计算,浮点数的计算要比定点数计算要慢,故并不是直接使用1.5*thiz->alloc_size.又由于若编译器不做优化,则除法操作也较慢,故也不使用thiz->alloc_size+thiz->alloc_size/2.
    而size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1)则是最快的方法。后面加上MIN_PRE_ALLOCATE_NR是为避免当thiz->alloc_size为0时存在的错误。

(4)动态数组 减小函数
/**
 * @function:动态数组  减小空间函数
 * 
 * @param thiz:  		指向动态数组
 * @return:				运行状态
 * @description:
 * 当  实际空间大小的一半 还大于当前数组大小 且 实际空间大小 要大于 固定值 (预防为0的情况)时,减小为有效空间的1.5倍。
 * 注:删除元素时也并不是马上释放空间,而是等空闲空间高于某个值才释放它们。
*/
static Ret darray_shrink(DArray* thiz)
{
	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); 	//若不存在则直接返回错误

	if((thiz->size < (thiz->alloc_size >> 1)) && (thiz->alloc_size > MIN_PRE_ALLOCATE_NR))//若现有大小 < 已分配1/2倍 且 已分配空间>最小空间
	{
		size_t alloc_size = thiz->size + (thiz->size >> 1);								  //将空间大小缩小为现有的1.5倍

		void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);
		if(data != NULL)
		{
			thiz->data = data;
			thiz->alloc_size = alloc_size;
		}
	}

	return RET_OK;
}
(5)动态数组 插入函数(包含头插法与尾插法)
/**
 * @function:动态数组 插入函数
 * 
 * @param thiz:		指向动态数组
 * @param index:	插入的位置
 * @param data:		插入的数据
 * 
 * @return:			运行状态
 * @description:
*/
Ret darray_insert(DArray* thiz, size_t index, void* data)
{
	Ret ret = RET_OOM;											//定义返回状态初始值为OOM
	size_t cursor = index;										//形参:数组下标或称游标(插入的位置)
	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); 		//若对象为空,则报错为无效参数

	cursor = cursor < thiz->size ? cursor : thiz->size;			//确认插入元素的位置

	if(darray_expand(thiz, 1) == RET_OK)						//若成功扩展空间,则将游标以后位置数据后移一个单位后,将指定位置赋值且数组长度变量+1
	{
		size_t i = 0;
		for(i = thiz->size; i > cursor; i--)
		{
			thiz->data[i] = thiz->data[i-1];
		}

		thiz->data[cursor] = data;
		thiz->size++;
		
		ret = RET_OK;
	}

	return ret;
}

/**
 * @function:	头插法
 * 
 * @param thiz:		指向动态数组
 * @param data:		插入的数据
 * 
 * @return:			运行状态
 * @description:
*/
Ret darray_prepend(DArray* thiz, void* data)
{
	return darray_insert(thiz, 0, data);
}

/**		
 * @function:	尾插法
 * 
 * @param thiz:		指向动态数组
 * @param data:		插入的数据
 * 
 * @return:			运行状态
 * @description:
*/
Ret darray_append(DArray* thiz, void* data)
{
	return darray_insert(thiz, -1, data);
}
(6)动态数组 删除函数
/**
 * @function: 动态数组 删除数据
 * 
 * @param thiz:		指向动态数组
 * @param data:		数据
 * 
 * @return:		无
 * @description:
 * 	销毁函数在创建时有使用者进行编写
*/
static void darray_destroy_data(DArray* thiz, void* data)
{
	if(thiz->data_destroy != NULL)
	{
		thiz->data_destroy(thiz->data_destroy_ctx, data);
	}

	return;
}

/**
 * @function:动态数组 删除函数
 * 
 * @param thiz:			指向动态数组对象
 * @param index:		指定下标位置
 * 	
 * @return:				执行状态
 * @description:
 * 		删除指定位置数据,数组元素前移。
*/
Ret darray_delete(DArray* thiz, size_t index)
{
	size_t i = 0;
	Ret ret = RET_OK;

	return_val_if_fail(thiz != NULL && thiz->size > index, RET_INVALID_PARAMS); 	//若动态数组不存在且删除位置大于数组大小

	darray_destroy_data(thiz, thiz->data[index]);				//删除指定位置数据
	for(i = index; (i+1) < thiz->size; i++)						//将删除后的数组元素前移
	{
		thiz->data[i] = thiz->data[i+1];
	}
	thiz->size--;

	darray_shrink(thiz);		//检查是否需要减小空间

	return RET_OK;
}
(7)动态数组 销毁函数
/**
 * @function:  动态数组 销毁函数
 * 
 * @param thiz:	指向动态数组
 * 
 * @return:	无
 * @description:
 * 		删除所有数据,销毁动态数组,销毁动态数组空间
*/
void darray_destroy(DArray* thiz)
{
	size_t i = 0;
	
	if(thiz != NULL)
	{
		for(i = 0; i < thiz->size; i++)
		{
			darray_destroy_data(thiz, thiz->data[i]);
		}
		
		SAFE_FREE(thiz->data);
		SAFE_FREE(thiz);
	}

	return;
}

3.书中程序

typedef.h
/*
 * File:    typedef.h
 * Author:  Li XianJing <xianjimli@hotmail.com>
 * Brief:   common types definition.
 *
 * Copyright (c) Li XianJing
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * History:
 * ================================================================
 * 2008-12-10 Li XianJing <xianjimli@hotmail.com> created.
 *
 */

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#ifndef TYPEDEF_H
#define TYPEDEF_H

typedef enum _Ret
{
	RET_OK,
	RET_OOM,
	RET_STOP,
	RET_INVALID_PARAMS,
	RET_FAIL
}Ret;

typedef void     (*DataDestroyFunc)(void* ctx, void* data);
typedef int      (*DataCompareFunc)(void* ctx, void* data);
typedef Ret      (*DataVisitFunc)(void* ctx, void* data);

#ifdef __cplusplus
#define DECLS_BEGIN extern "C" {
#define DECLS_END   }
#else
#define DECLS_BEGIN
#define DECLS_END
#endif/*__cplusplus*/

#define return_if_fail(p) if(!(p)) \
	{printf("%s:%d Warning: "#p" failed.\n", \
		__func__, __LINE__); return;}
#define return_val_if_fail(p, ret) if(!(p)) \
	{printf("%s:%d Warning: "#p" failed.\n",\
	__func__, __LINE__); return (ret);}

#define SAFE_FREE(p) if(p != NULL) {free(p); p = NULL;}

typedef Ret (*SortFunc)(void** array, size_t nr, DataCompareFunc cmp);

#endif/*TYPEDEF_H*/

darray.h
/*
 * File:    darray.h
 * Author:  Li XianJing <xianjimli@hotmail.com>
 * Brief:   dynamic array implementation.
 *
 * Copyright (c) Li XianJing
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * History:
 * ================================================================
 * 2009-01-02 Li XianJing <xianjimli@hotmail.com> created
 */

#include <stdio.h>
#include "typedef.h"

#ifndef DARRAY_H
#define DARRAY_H

DECLS_BEGIN

struct _DArray;
typedef struct _DArray DArray;

DArray* darray_create(DataDestroyFunc data_destroy, void* ctx);

Ret    darray_insert(DArray* thiz, size_t index, void* data);
Ret    darray_prepend(DArray* thiz, void* data);
Ret    darray_append(DArray* thiz, void* data);
Ret    darray_delete(DArray* thiz, size_t index);
Ret    darray_get_by_index(DArray* thiz, size_t index, void** data);
Ret    darray_set_by_index(DArray* thiz, size_t index, void* data);
size_t darray_length(DArray* thiz);
int    darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx);
Ret    darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx);

void darray_destroy(DArray* thiz);

DECLS_END

#endif/*DARRAY_H*/

darray.c
/*
 * File:    darray.c
 * Author:  Li XianJing <xianjimli@hotmail.com>
 * Brief:   dynamic array implementation.
 *
 * Copyright (c) Li XianJing
 *
 * Licensed under the Academic Free License version 2.1
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * History:
 * ================================================================
 * 2009-01-02 Li XianJing <xianjimli@hotmail.com> created
 *
 */

#include <stdlib.h>
#include "darray.h"

struct _DArray
{
	void** data;
	size_t size;
	size_t alloc_size;

	void* data_destroy_ctx;
	DataDestroyFunc data_destroy;
};

static void darray_destroy_data(DArray* thiz, void* data)
{
	if(thiz->data_destroy != NULL)
	{
		thiz->data_destroy(thiz->data_destroy_ctx, data);
	}

	return;
}

DArray* darray_create(DataDestroyFunc data_destroy, void* ctx)
{
	DArray* thiz = malloc(sizeof(DArray));

	if(thiz != NULL)
	{
		thiz->data  = NULL;
		thiz->size  = 0;
		thiz->alloc_size = 0;
		thiz->data_destroy = data_destroy;
		thiz->data_destroy_ctx = ctx;
	}

	return thiz;
}

#define MIN_PRE_ALLOCATE_NR 10
static Ret darray_expand(DArray* thiz, size_t need)
{
	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); 

	if((thiz->size + need) > thiz->alloc_size)
	{
		size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;

		void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);
		if(data != NULL)
		{
			thiz->data = data;
			thiz->alloc_size = alloc_size;
		}
	}

	return ((thiz->size + need) <= thiz->alloc_size) ? RET_OK : RET_FAIL;
}

static Ret darray_shrink(DArray* thiz)
{
	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); 

	if((thiz->size < (thiz->alloc_size >> 1)) && (thiz->alloc_size > MIN_PRE_ALLOCATE_NR))
	{
		size_t alloc_size = thiz->size + (thiz->size >> 1);

		void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);
		if(data != NULL)
		{
			thiz->data = data;
			thiz->alloc_size = alloc_size;
		}
	}

	return RET_OK;
}

Ret darray_insert(DArray* thiz, size_t index, void* data)
{
	Ret ret = RET_OOM;
	size_t cursor = index;
	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); 

	cursor = cursor < thiz->size ? cursor : thiz->size;

	if(darray_expand(thiz, 1) == RET_OK)
	{
		size_t i = 0;
		for(i = thiz->size; i > cursor; i--)
		{
			thiz->data[i] = thiz->data[i-1];
		}

		thiz->data[cursor] = data;
		thiz->size++;
		
		ret = RET_OK;
	}

	return ret;
}

Ret darray_prepend(DArray* thiz, void* data)
{
	return darray_insert(thiz, 0, data);
}

Ret darray_append(DArray* thiz, void* data)
{
	return darray_insert(thiz, -1, data);
}

Ret darray_delete(DArray* thiz, size_t index)
{
	size_t i = 0;
	Ret ret = RET_OK;

	return_val_if_fail(thiz != NULL && thiz->size > index, RET_INVALID_PARAMS); 

	darray_destroy_data(thiz, thiz->data[index]);
	for(i = index; (i+1) < thiz->size; i++)
	{
		thiz->data[i] = thiz->data[i+1];
	}
	thiz->size--;

	darray_shrink(thiz);

	return RET_OK;
}

Ret darray_get_by_index(DArray* thiz, size_t index, void** data)
{

	return_val_if_fail(thiz != NULL && data != NULL && index < thiz->size, 
		RET_INVALID_PARAMS); 

	*data = thiz->data[index];

	return RET_OK;
}

Ret darray_set_by_index(DArray* thiz, size_t index, void* data)
{
	return_val_if_fail(thiz != NULL && index < thiz->size, 
		RET_INVALID_PARAMS); 

	thiz->data[index] = data;

	return RET_OK;
}

size_t   darray_length(DArray* thiz)
{
	size_t length = 0;
	
	return_val_if_fail(thiz != NULL, 0);

	return thiz->size;
}

Ret darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx)
{
	size_t i = 0;	
	Ret ret = RET_OK;
	return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);

	for(i = 0; i < thiz->size; i++)
	{
		ret = visit(ctx, thiz->data[i]);
	}

	return ret;
}

int      darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx)
{
	size_t i = 0;

	return_val_if_fail(thiz != NULL && cmp != NULL, -1);

	for(i = 0; i < thiz->size; i++)
	{
		if(cmp(ctx, thiz->data[i]) == 0)
		{
			break;
		}
	}

	return i;
}

void darray_destroy(DArray* thiz)
{
	size_t i = 0;
	
	if(thiz != NULL)
	{
		for(i = 0; i < thiz->size; i++)
		{
			darray_destroy_data(thiz, thiz->data[i]);
		}
		
		SAFE_FREE(thiz->data);
		SAFE_FREE(thiz);
	}

	return;
}

#ifdef DARRAY_TEST

#include <assert.h>

static int int_cmp(void* ctx, void* data)
{
	return (int)data - (int)ctx;
}

static Ret print_int(void* ctx, void* data)
{
	printf("%d ", (int)data);

	return RET_OK;
}

static Ret check_and_dec_int(void* ctx, void* data)
{
	int* expected =(int*)ctx;
	assert(*expected == (int)data);

	(*expected)--;

	return RET_OK;
}

static void test_int_darray(void)
{
	int i = 0;
	int n = 100;
	int data = 0;
	DArray* darray = darray_create(NULL, NULL);

	for(i = 0; i < n; i++)
	{
		assert(darray_append(darray, (void*)i) == RET_OK);
		assert(darray_length(darray) == (i + 1));
		assert(darray_get_by_index(darray, i, (void**)&data) == RET_OK);
		assert(data == i);
		assert(darray_set_by_index(darray, i, (void*)(2*i)) == RET_OK);
		assert(darray_get_by_index(darray, i, (void**)&data) == RET_OK);
		assert(data == 2*i);
		assert(darray_set_by_index(darray, i, (void*)i) == RET_OK);
		assert(darray_find(darray, int_cmp, (void*)i) == i);
	}

	for(i = 0; i < n; i++)
	{
		assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
		assert(data == (i));
		assert(darray_length(darray) == (n-i));
		assert(darray_delete(darray, 0) == RET_OK);
		assert(darray_length(darray) == (n-i-1));
		if((i + 1) < n)
		{
			assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
			assert((int)data == (i+1));
		}
	}
	
	assert(darray_length(darray) == 0);

	for(i = 0; i < n; i++)
	{
		assert(darray_prepend(darray, (void*)i) == RET_OK);
		assert(darray_length(darray) == (i + 1));
		assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
		assert(data == i);
		assert(darray_set_by_index(darray, 0, (void*)(2*i)) == RET_OK);
		assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);
		assert(data == 2*i);
		assert(darray_set_by_index(darray, 0, (void*)i) == RET_OK);
	}

	i = n - 1;
	assert(darray_foreach(darray, check_and_dec_int, &i) == RET_OK);

	darray_destroy(darray);

	return;
}

static void test_invalid_params(void)
{
	printf("===========Warning is normal begin==============\n");
	assert(darray_length(NULL) == 0);
	assert(darray_prepend(NULL, 0) == RET_INVALID_PARAMS);
	assert(darray_append(NULL, 0) == RET_INVALID_PARAMS);
	assert(darray_delete(NULL, 0) == RET_INVALID_PARAMS);
	assert(darray_insert(NULL, 0, 0) == RET_INVALID_PARAMS);
	assert(darray_set_by_index(NULL, 0, 0) == RET_INVALID_PARAMS);
	assert(darray_get_by_index(NULL, 0, NULL) == RET_INVALID_PARAMS);
	assert(darray_find(NULL, NULL, NULL) < 0);
	assert(darray_foreach(NULL, NULL, NULL) == RET_INVALID_PARAMS);
	printf("===========Warning is normal end==============\n");

	return;
}

static void single_thread_test(void)
{
	test_int_darray();
	test_invalid_params();

	return;
}

int main(int argc, char* argv[])
{
	single_thread_test();

	return 0;
}
#endif

Makefile
CFILES=darray.c
all:
        gcc -g -shared -lpthread $(CFILES) -o libdarray.so
        gcc -g -DDARRAY_TEST -lpthread $(CFILES)  -o darray_test

clean:
        rm -f *test *.exe *.so

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值