在开发过程中,经常会遇到想要申请的内存长度不固定的情况,在一般效率不高时,直接使用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
#endifstruct 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 usearraysmartBuf->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 mallocif(!_Smart_Buf_AddBuf(smartBuf,strlen(dataBuf) + DEFAULT_BUF_LEN))return false;}if(smartBuf->bUseHeap){//use buffersprintf(smartBuf->buf,"%s",dataBuf);smartBuf->used_len = strlen(smartBuf->buf);}else{//use arraysprintf(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;
}

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

  1. java创建对象时分配内存方式,是堆上分配还是栈上分配?

    创建对象的内存是分配在堆上还是栈上面?大部分童鞋的回答是这样的:"肯定分配在堆内存的嘛,栈内存是属于子线程和基本数据类型专用的内存空间,怎么会分配到栈上面呢?",这个回答嘛,也对, ...

  2. C++中栈和堆上建立对象的区别

    在C++中类的对象建立分为两种,一种是静态建立,如A a:另一种是动态建立,如A* p=new A(),A*p=(A*)malloc():静态建立一个类对象,是由编译器为对象在栈空间中分配内存,通过直 ...

  3. C++ 栈和堆上建立对象的区别

    在C++中类的对象建立分为两种,一种是静态建立,如A a:另一种是动态建立,如A* p=new A(),Ap=(A)malloc():静态建立一个类对象,是由编译器为对象在栈空间中分配内存,通过直接移 ...

  4. 【性能优化】面试官:Java中的对象和数组都是在堆上分配的吗?

    写在前面 从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:"Jav ...

  5. Java 对象都是在堆上分配内存吗?

    为了防止歧义,可以换个说法:Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定.满足特定条件时,它们可以在(虚拟机)栈上分配内存. JVM内存结构很重要,多多复习 这和我们平时的理解可能有 ...

  6. 对象并不一定都是在堆上分配内存的

    JVM内存分配策略 关于JVM的内存结构及内存分配方式,不是本文的重点,这里只做简单回顾.以下是我们知道的一些常识: 1.根据Java虚拟机规范,Java虚拟机所管理的内存包括方法区.虚拟机栈.本地方 ...

  7. Java对象都是在堆上分配空间吗?答案竟然是...

    作者 l Hollis 来源 l Hollis(ID:hollischuang) Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或 ...

  8. java 堆_Java 对象都是在堆上分配内存吗?

    为了防止歧义,可以换个说法:Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定.满足特定条件时,它们可以在(虚拟机)栈上分配内存. JVM内存结构很重要,多多复习 这和我们平时的理解可能有 ...

  9. java如何定义一个变长数组_如何自定义一个长度可变数组

    摘要:本文主要写了如何自定义一个长度可变数组 数组是在程序设计中,为了处理方便,把具有相同类型的若干元素按无序的形式组织起来的一种形式 在定义之初,数组的长度就被定义 新建数组有很多方式 下面两个都可 ...

最新文章

  1. lolfps高但画面不流畅_你吃鸡卡吗,超详细和平精英画面设置教程,解决卡顿,主播都在用...
  2. CheckBox in ListView
  3. Python发送邮件以及自动化测试报告的生成
  4. [Socket网络编程]一个封锁操作被对 WSACancelBlockingCall 的调用中断。
  5. SAP CRM和Cloud for Customer的UI界面皮肤更改
  6. 程序员面试金典 - 面试题 04.06. 后继者(循环中序遍历)
  7. 在html中写js提示错误,页面HTML标签优化
  8. 【pytorch】pytorch-LSTM
  9. table标签中 如何固定td 宽度
  10. vue如何编写组件可以通过Vue.use()使用
  11. rubyinstaller官方下载
  12. Word如何让样式库中的样式不添加到自动生成的目录中
  13. python3怎么将函数的用法通过help导出到文件
  14. Good Bye 2020 B
  15. 好的电子书资源——原创力文档
  16. 数据结构之你没见过的排序算法!
  17. 惠普linux进入bios设置u盘启动,hp惠普笔记本进入bios设置u盘启动装系统的方法步骤详细教程 - 系统家园...
  18. REW声学测试(二):离线测试
  19. 20211219 小信号建模——状态空间法
  20. SAP中科目货币及本位币记账控制测试

热门文章

  1. Windows将WSL 1升级为WSL2
  2. MySQL统计两部分查询结果记录数量比值
  3. JAVA :RESTLET开发实例(一)基于JAX-RS的REST服务
  4. mysql 自定义函数 找不到表_mysql 自定义函数
  5. java 私有成员方法_Java Reflection 教程(7):类私有成员变量和方法
  6. android listview 移动到顶部,android listview滚动到顶部
  7. HTML form -enctype
  8. 2.Java 面试题整理(基础篇二)
  9. Python学习笔记:字典(dict)
  10. Python程序:输出斐波那契数列