注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

逍遥子 曰:

得失失得 何必患得患失 舍得得舍 不妨不舍不得

 
 
 

日志

 
 

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

2013-12-20 16:07:11|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

      在开发过程中,经常会遇到想要申请的内存长度不固定的情况,在一般效率不高时,直接使用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;
}


  评论这张
 
阅读(578)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017