C 语言泛型Array数组封装

    以前,写过一个C 语言泛型数组实现,但在实际的使用过程中,发现了更加易用的模式,进行了改进。这个数组封装作为一个最基础的结构,在此之上实现了动态数组,队列,数组映射等。还利用这些数据结构实现了一个简单的json解析器,已经成为C工具箱的最基础工具,可以验证这些结构的可用性和稳定性,以后将逐步介绍。

   

    这个泛型数组分为代码实现和宏定义两部分,主要完成以下功能。

  • 可存储任意数据类型数据
  • 带有数据长度
  • 一套便捷使用的宏定义接口
  • 可以在堆上,也可以在栈上使用


    首先看代码实现部分,非常的简单。

typedef struct
{
	/** Elements memory data */
	void* data;
	/** Elements count */
	int   length;
}
Array;


typedef struct
{
	/**
	 * Array space and data space in one malloc
	 * Array data hold the offset of malloc return address
	 */
	Array* (*Create)(int typeSize, int length);
}
_AArray_;

extern _AArray_ AArray[1];

static Array* Create(int typeSize, int length)
{
	Array* array  = (Array*) malloc(sizeof(Array) + typeSize * length);
	array->data   = (char*) array + sizeof(Array);
	array->length = length;

	return array;
}

_AArray_ AArray[1] =
{
	Create,
};

   Create是在堆上分配空间,这里我们采用了折叠空间的方法,是的Array本身的空间和元素的空间一次性分配,用过data指针持有元素空间的偏移地址。这样的好处就是分配和释放只需要一次。


    然后,是一组宏定义的访问接口。
    
/** The type is the array element type */
#define Array(type) Array

/**
 * The type is element type
 */
#define AArray_GetData(array, type) \
	(type*) ((array)->data)

/**
 * return element
 */
#define AArray_Get(array, index, type) \
	(AArray_GetData(array, type))[index]

/**
 * return element ptr
 */
#define AArray_GetPtr(array, index, type) \
	(AArray_GetData(array, type) + index)

/**
 * set element
 */
#define AArray_Set(array, index, element, type) \
	AArray_Get(array, index, type) = element

    
    标示性宏定义  #define Array(type) Array 的意义就是在定义的时候,可以明确Array元素的类型,虽然编译器没有像泛型那样的类型检查,但C中可以增加可读性。然后就是一组对元素的get,set访问方法。那么,Get和GetPtr的区别就在于。元素是指针的时候Get返回指针,元素是结构对象的时候Get回返回对象,这样会产生栈上的结构对象复制。而这个时候使用GetPtr能获得元素对象的指针,不会复制元素对象的结构内容。


   特别介绍两个宏定义。
   
/**
 * Create Array composite literal
 */
#define AArray_Create(type, length, ...) \
	(Array[1])                           \
	{                                    \
		(type[length]) { __VA_ARGS__ },  \
		length,                          \
	}

/**
 * Init constant Array
 */
#define AArray_Init(type, length, ...)  \
	{                                   \
		(type[length]) { __VA_ARGS__ }, \
		length,                         \
	}

     这两个宏定义,都是在栈上分配数组空间并初始化。使用了C99变参宏替换,这样数组元素可以传入变参数据。另外,第一个使用了C99的 复合字面量。这两个定义的使用区别在于,第一个可以赋值给变量,第二个是在结构对象定义中嵌入字面量。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值