一个自动在栈和堆上分配变长数组的实现方式

117 篇文章 6 订阅
33 篇文章 5 订阅

      在开发过程中,经常会遇到想要申请的内存长度不固定的情况,在一般效率不高时,直接使用malloc或者free就可以,但是在一些效率要求较高的场合,频繁的使用malloc和free会严重影响到系统的性能。在大多数情况下,我们遇到的情况都是:申请的长度一般都在某个值之下,特殊情况下,会出现长度大于此值;这时候如果使用一个定长的数组,则可以显著提升系统效率,但是又照顾不了个别情况下数组无法装下的问题,并且长度不太好确定,太长会浪费空间,太短又可能不够用;如果使用malloc动态申请内存,虽然能够满足各种长度要求,但是会对效率产生显著的影响;如何兼顾效率和空间浪费是个两难的问题

      下面的这段代码可以自动在栈和堆之间进行切换,使用时只需要根据经验值设定一个固定大小,经验值之内的内存自动在栈上定义,大于经验值的内存都在堆上分配,它实现的原理是:在结构体内部定义一个定长数组和一个指针,如果用户需要的长度小于数组长度,则直接使用数组,无需在堆上申请内存,如果用户使用过程中,需要的长度增加了,并且超过了定长数组,则自动在堆上申请内存,并将数据从数组中转移过来,定长数组的长度为宏DEFAULT_BUF_LEN,可根据自己的经验值进行修改,上述的这些过程对使用着来说是透明的。这段代码包括了实现代码,以及一个简单的使用及测试用例;

      下面的代码提供了6个接口函数,其名称和功能为:

1、bool Smart_Buf_Init(struct Smart_Buffer* smartBuf, int len);它主要完成对结构体struct Smart_Buffer的初始化工作,并可指定长度,如果指定长度小于宏DEFAULT_BUF_LEN,则指定长度不被采用;

2、void Smart_Buf_Uninit(struct Smart_Buffer* smartBuf);主要对结构体struct Smart_Buffer的反初始化工作,如果内部有从堆中申请了内存,则在该函数内部会进行释放;

3、bool Smart_Buf_SetData(struct Smart_Buffer* smartBuf, char* dataBuf);该接口主要完成存储一个buf的功能;

4、bool Smart_Buf_StrCat(struct Smart_Buffer* smartBuf, char* dataBuf);该接口主要将dataBuf中的内容拼接到smartBuf中;

5、char* Smart_Buf_GetBuf(struct Smart_Buffer* smartBuf);该接口可以获取smartBuf中正在使用的内存的地址,如果使用的是定长数组,则返回数组的首地址,如果是从堆中新申请的内存,则返回该内存的地址。

6、void Smart_Buf_description(struct Smart_Buffer* smartBuf);该接口函数可以打印smartBuf中的内部情况;


需要注意的是:

1、使用之前一定要先调用初始化接口:使用结束一定要调用反初始化接口

2、使用过程中尽量使用接口函数对内存进行操作,而不是直接操纵结构体内的内存。

           

/*******************************************Smart_Buffer*****************************************************
*说明:
*功能:
*接口函数说明:
*使用示例:
*注意:
*	开始使用时需调用:Smart_Buf_Init
*	使用结束需要调用:Smart_Buf_Uninit
*******************************************Smart_Buffer*****************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define DEFAULT_BUF_LEN 1024


#ifndef bool
#define bool char
#endif

#ifndef true
#define true 1
#endif

#ifndef false
#define false 0
#endif


struct Smart_Buffer{
	bool bUseHeap;
	char* buf;
	char array[DEFAULT_BUF_LEN];
	int capacity;
	int used_len;
};

bool Smart_Buf_Init(struct Smart_Buffer* smartBuf, int len);
bool Smart_Buf_SetData(struct Smart_Buffer* smartBuf, char* dataBuf);
bool Smart_Buf_StrCat(struct Smart_Buffer* smartBuf, char* dataBuf);
void Smart_Buf_Uninit(struct Smart_Buffer* smartBuf);
static bool _Smart_Buf_AddBuf(struct Smart_Buffer* smartBuf,int len);
void Smart_Buf_description(struct Smart_Buffer* smartBuf);
char* Smart_Buf_GetBuf(struct Smart_Buffer* smartBuf);


bool Smart_Buf_Init(struct Smart_Buffer* smartBuf,int len)
{
	if(NULL == smartBuf)
		return false;
	smartBuf->buf = NULL;
	if(len < DEFAULT_BUF_LEN){//Request buffer length is less than default length,will usearray
		smartBuf->capacity = DEFAULT_BUF_LEN;
		smartBuf->bUseHeap = false;
		memset(smartBuf->array, '\0', smartBuf->capacity);
	}else{	// Request buffer length is longer than default length,will malloc memory;
		smartBuf->capacity = len + DEFAULT_BUF_LEN;
		smartBuf->buf = malloc(smartBuf->capacity);
		if(NULL == smartBuf->buf)
			return false;
		smartBuf->bUseHeap = true;
		memset(smartBuf->buf, '\0', smartBuf->capacity);
	}
	smartBuf->used_len = 0;

	return true;
}

static bool _Smart_Buf_AddBuf(struct Smart_Buffer* smartBuf,int len)
{
	if(NULL == smartBuf || len <= 0)
		return false;
	if(smartBuf->capacity >= len)
		return true;
	int new_len = len + DEFAULT_BUF_LEN;

	if(smartBuf->bUseHeap){
		smartBuf->buf = realloc(smartBuf->buf, new_len * sizeof(char));
	}else{
		smartBuf->buf = malloc(new_len* sizeof(char));
		memset(smartBuf->buf, '\0',new_len * sizeof(char));
		strncpy(smartBuf->buf,smartBuf->array,smartBuf->used_len);
		memset(smartBuf->array, '\0',DEFAULT_BUF_LEN);
		smartBuf->bUseHeap = true;
	}
	smartBuf->capacity = new_len;
	return true;
}


bool Smart_Buf_SetData(struct Smart_Buffer* smartBuf, char* dataBuf)
{
	if(NULL == smartBuf)
		return false;
	if(NULL == dataBuf)
		return true;

	if(smartBuf->capacity < strlen(dataBuf)){//capacity of smartBuf is less than the lenght of dataBuf,will malloc
		if(!_Smart_Buf_AddBuf(smartBuf,strlen(dataBuf) + DEFAULT_BUF_LEN))
			return false;
	}
	
	if(smartBuf->bUseHeap){//use buffer
		sprintf(smartBuf->buf,"%s",dataBuf);
		smartBuf->used_len = strlen(smartBuf->buf);
	}else{//use array
		sprintf(smartBuf->array,"%s",dataBuf);
		smartBuf->used_len = strlen(smartBuf->array);
	}
	return true;
}

bool Smart_Buf_StrCat(struct Smart_Buffer* smartBuf, char* dataBuf)
{
	if(NULL == smartBuf)
		return false;
	if(NULL == dataBuf)
		return true;
	int new_len = 0;
	if(smartBuf->capacity < strlen(dataBuf)+ smartBuf->used_len){
		if(!_Smart_Buf_AddBuf(smartBuf,strlen(dataBuf)+ smartBuf->used_len))
			return false;
	}
	if(smartBuf->bUseHeap){
		strcat(smartBuf->buf,dataBuf);
		smartBuf->used_len = strlen(smartBuf->buf);
	}else{
		strcat(smartBuf->array,dataBuf);
		smartBuf->used_len = strlen(smartBuf->array);
	}

	return true;
}

void Smart_Buf_Uninit(struct Smart_Buffer* smartBuf)
{
	if(NULL == smartBuf)
		return ;

	if(smartBuf->bUseHeap && NULL != smartBuf->buf)
		free(smartBuf->buf);
	smartBuf->bUseHeap = false;
	smartBuf->buf = NULL;
	smartBuf->capacity = DEFAULT_BUF_LEN;
}

char* Smart_Buf_GetBuf(struct Smart_Buffer* smartBuf)
{
	if(NULL == smartBuf)
		return NULL;
	return smartBuf->bUseHeap ? smartBuf->buf : smartBuf->array;
	
}

void Smart_Buf_description(struct Smart_Buffer* smartBuf)
{
	if(NULL == smartBuf)
		return ;

	printf("\n|---------- description of struct Smart_Buffer:----------| \n");
	printf(" smartBuf address   : [%p]\n",smartBuf);
	printf("   Is use heap      : [%s]\n",smartBuf->bUseHeap ? "Yes" : "No");
	printf("   capacity         : [%d]\n",smartBuf->capacity);
	printf("   used length      : [%d]\n",smartBuf->used_len);
	printf("   - array address  : [%p]\n",smartBuf->array);
	printf("   - array content  : [%s]\n",smartBuf->array);
	printf("   - buffer address : [%p]\n",smartBuf->buf);
	printf("   - buffer content : [%s]\n\n",smartBuf->buf ? smartBuf->buf : "NULL");
}

/*----------------------test------------------------------*/
void test1()
{
	printf("\n------------into function:test1()\n");
	struct Smart_Buffer mySmartBuf;
	printf("\n will init buffer length 5 (default length is 10)\n");
	if(!Smart_Buf_Init(&mySmartBuf,5)){
		printf("fail from function:Smart_Buf_Init\n");
		return ;
	}
	printf("\n after Smart_Buf_Init():\n");
	Smart_Buf_description(&mySmartBuf);
	
	printf("\n will set data:[hello ]\n");
	if(!Smart_Buf_SetData(&mySmartBuf,"hello ")){
		printf("fail from function:Smart_Buf_SetData\n");
		return ;
	}
	printf("\n after Smart_Buf_SetData():\n");
	Smart_Buf_description(&mySmartBuf);

	printf("***test-Smart_Buf_GetBuf -content:[%s]***\n",Smart_Buf_GetBuf(&mySmartBuf));

	
	printf("\n will call Smart_Buf_StrCat with:[this is jason!]\n");
	if(!Smart_Buf_StrCat(&mySmartBuf, " this is jason! ")){
		printf("fail from function:Smart_Buf_StrCat\n");
		return ;
	}
	printf("\n after Smart_Buf_StrCat():\n");
	Smart_Buf_description(&mySmartBuf);

	printf("***test-Smart_Buf_GetBuf -content:[%s]***\n",Smart_Buf_GetBuf(&mySmartBuf));
	
	printf("\n will unit buffer...\n");
	Smart_Buf_Uninit(&mySmartBuf);
	printf("\n after Smart_Buf_Uninit():\n");
	Smart_Buf_description(&mySmartBuf);

}

/*----------------------------------------------------*/
void test2()
{
	printf("\n------------into function:test2()\n");
	struct Smart_Buffer mySmartBuf;
	printf("\n will init buffer length 20(default length is 10)\n");
	if(!Smart_Buf_Init(&mySmartBuf,20)){
		printf("fail from function:Smart_Buf_Init\n");
		return ;
	}
	printf("\n after Smart_Buf_Init():\n");
	Smart_Buf_description(&mySmartBuf);
	
	printf("\n will set data:[hello, this jason, and  i am from XI'AN,china..................... ]\n");
	if(!Smart_Buf_SetData(&mySmartBuf,"hello, this jason, and  i am from XI'AN,china..................... ")){
		printf("fail from function:Smart_Buf_SetData\n");
		return ;
	}
	printf("\n after Smart_Buf_SetData():\n");
	Smart_Buf_description(&mySmartBuf);

	printf("***test-Smart_Buf_GetBuf -content:[%s]***\n",Smart_Buf_GetBuf(&mySmartBuf));
	
	printf("\n will call Smart_Buf_StrCat with:[ <><><><><><><><><><><><><><><><><><><><><><><><><><><><><>]  \n");
	if(!Smart_Buf_StrCat(&mySmartBuf, " <><><><><><><><><><><><><><><><><><><><><><><><><><><><><>")){
		printf("fail from function:Smart_Buf_StrCat\n");
		return ;
	}
	printf("\n after Smart_Buf_StrCat():\n");
	Smart_Buf_description(&mySmartBuf);
	printf("\n will unit buffer...\n");

	printf("***test-Smart_Buf_GetBuf -content:[%s]***\n",Smart_Buf_GetBuf(&mySmartBuf));
	
	Smart_Buf_Uninit(&mySmartBuf);
	printf("\n after Smart_Buf_Uninit():\n");
	Smart_Buf_description(&mySmartBuf);

}

int main()
{
	test1();

	test2();

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值