目录:

1. 内存池

2. 栈

3. Hash表

1.内存池
  在一些小的程序里,没什么必要添加内存管理模块在里面。但是对于比较复杂的代码,如果需要很多的内存操作,那么加入自己的内存管理是有必要的。至少有一些好处:能够加快内存的申请和释放;能够轻松的查找内存泄露问题;能够对整个软件的内存消耗做一个比较精确的统计;对以后的优化有很大的好处等等。所以,在我的解释器里,我加入了一个简单的内存管理模块,仿造了内存池的做法。
  主要思想是这样的:
  a.记录所有的申请的内存
  b.当释放内存时,记录下来以供下次申请使用
  c.申请内存时,可以直接使用前面释放过的内存
  为了达到以上的功能。我为申请内存的大小划分粒度,例如:我得粒度这么安排{16,32,64,128,...}那么申请17个字节的大小时候,我会申请32个字节的大小。这样子方便管理。并且为每个粒度创建一个可用内存的双向链表。申请内存时,就可直接从这些链表头中申请(即将一个节点从链表头移除,作为被申请的空间,并插入到在使用的链表中),内存的释放则是一个想法的过程。这些的存储结构如下所示:
  
  (图1.1 内存池的存储结构)
  
typedef struct _pool_block{
    int size;
    void * data;
    struct _pool_block * next;
    struct _pool_block * pre;
}pool_block_t;

typedef struct _pool{
    int num_all;
    int num_free;
    pool_block_t * list_all;
    pool_block_t * list_free[POOL_ATOM_NUM];
}pool_t;

int pool_atom_tab[POOL_ATOM_NUM] = {
    32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, -1
};

说明:
  a.内存的申请会按照pool_atom_tab数组中的大小对齐,比如申请10byte,那么,我会申请32byte.
  b.为每个粒度保存一个双向链表,用于保存被释放的内存。如果要申请的内存超过8192,那么我直接调用系统的malloc,释放时,直接调用free.
  c.内存申请过程:到相应的粒度链表(list_free)中查看是否有可用内存,如果有,直接将它从该list_free链表中移动到list_all链表。
  d.内存释放过程:要释放的内存必定保存在list_all中,根据它的大小,把它移动到相应的list_free链表。
  e.pool_block_t结构被放置在申请内存的前面,则在释放时,直接根据Buffer指针就可得到pool_block_t的位置,从而得到next和pre,快速的在链表中移动。

2.栈
  栈在解释器中用到的地方很多,不管是表达式的解析,还是代码块的解析,类型的解析,等等都用到了栈。所以不实现它是不可能的事,不过在数据结构中他是最简单的了,无非就是申请一个空间,按一个一个的节点保存进去,按一个一个的节点取出来。没什么技巧在里面,只是这个我让栈的大小空间是自动增长和减小的,这么做的目的是:栈的空间仅仅限制于内存的大小。但是,这么做得缺点是,当栈的空间大小自动变化时,栈内的数据要被复制一遍,这务必会影响效率。但没有办法,暂时之能这样了。唯一的办法是在时间和空间上做一个选择。
  栈的存储结构如下:
  
  (图1.2 栈的存储结构)
  
typedef struct _stack{
    int item_len;
    int item_num;
    int stack_size;
    char *p;
}stack_t;
  
  说明:
  item_len:   保存每个节点的长度
  item_num:   栈中节点的个数
  stack_size: 栈中可保存的节点个数
  p:          指向栈空间
  a.当节点的个数item_num大于stack_size,那么必须重新申请空间,将原来的数据拷贝到新的空间。
  b.当节点的个数减小到一定的数量时,可以重新申请小的数据空间,释放原来大的空间。

3.hash表
  hash由于其快速的查找能力而著称,但是它太浪费内存了,所以用得的比较少,仅仅是在函数的调用时被使用。因为函数的调用是频繁的,如果从头查找函数,那将浪费很多的时间。这里引入hash也是必要的。
  
#define HH_TAB_SIZE 128

typedef struct _hh_node{
    unsigned int hash, klen, dlen;
    void * key;
    void * data;
    struct _hh_node *next;
}hh_node_t;

typedef struct _hh_head{
    unsigned int node_num;
    hh_node_t *  node_list;
}hh_head_t;

typedef struct _hh_hash{
    hh_opts_t opts;
    hh_head_t tabs[HH_TAB_SIZE];
}hh_hash_t;

typedef struct _hh_opts{
    int (*cmp_key)(void *key1, void *key2);
    unsigned int (*get_hash)(void *key);
    void * (*new_key)(int);
    void * (*new_data)(int);
    void (*del_key)(void *key);
    void (*del_data)(void *data);
}hh_opts_t;

C语言解释器的实现--存储结构(一)相关推荐

  1. 20.0、C语言数据结构——图的存储结构

    20.0.C语言数据结构--图的存储结构 图的存储结构相比较线性表与树来说就复杂很多了: 1. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放:树结构是一对多的关系,所以我 ...

  2. c语言线性表链路存储结构运用,哈尔滨工业大学2020年考研854计算机基础考试大纲...

    考研大纲是2020考研学生复习的重要参考资料,它指出了所考科目的大致考试范围,也是考研命题的重要参考依据.2020考研大纲已经陆续公布,包括公共课考试大纲和专业课统考科目考试大纲,而自命题科目考试大纲 ...

  3. 分段地址变换过程c语言,段页式存储结构

    段.页式存储都是采用离散分配方式的.离散分配方式:允许一个进程直接分散地装入到许多不相临的分区中,可以更好的提高内存利用率. 一.基本分页存储 1.分页存储方式原则 把逻辑进程分为若干页:把实际内存分 ...

  4. 用c语言实现串的存储结构是指,数据结构学习笔记-串(C语言实现)

    串由零个或多个字符组成,说白了就是字符串.串的存储方式相对于线性表来讲有些不同,他分为以下几种:顺序存储.堆分配存储.链式存储.顺序存储通常在数组中的头元素存放字符串长度.堆分配存储通常会动态分配空间 ...

  5. 《数据结构》c语言版学习笔记——其他链表(线性表的链式存储结构Part2)

    线性表的链式存储结构 数据结构系列文章 第三章 循环链表.双向链表 文章目录 线性表的链式存储结构 前言 一.循环链表 (一)定义 (二)尾指针 二.双向链表 (一)定义 (二)代码 总结 前言 提示 ...

  6. 《数据结构》c语言版学习笔记——单链表结构(线性表的链式存储结构Part1)

    线性表的链式存储结构 数据结构系列文章 第二章 单链表结构 文章目录 线性表的链式存储结构 前言 一.单链表的建立 代码 二.单链表的读取 代码 三.单链表的插入 代码 四.单链表的删除 代码 五.单 ...

  7. 线性表的链式存储结构(C语言版)

    上一篇博文我对数据结构中线性表的顺序存储结构顺序表(http://12172969.blog.51cto.com/12162969/1916336)按照我的理解做了总结,今天我继续对顺序表的另一种存储 ...

  8. C语言手写二叉树(链式存储结构)

    C语言手写二叉树(链式存储结构) 二叉树结构 二叉树基本运算 代码 图例(main函数执行过程如下:) 阶段I 阶段II 阶段III 阶段IV 阶段V 先序遍历输出过程 二叉树结构 二叉树可以用顺序存 ...

  9. c51语言的数据存储模式,第5章项目三单片机存储结构及C51语言.ppt

    第5章项目三单片机存储结构及C51语言 项目三 基本功 任务一 MCS-51单片机基础 任务二 单片机C51语言程序设计基础 二.MCS-51单片机存储器及存储空间 1.存储器的概念 什么是存储器呢? ...

最新文章

  1. 备忘录:CISCO router ENABLE crack
  2. 电脑删除linux系统,我的电脑现在装有XP和Linux两个系统,现在想删除Linux系统,开机不用选直接进入XP。不知怎么做??...
  3. 项目下创建文件_Linux 下创建和使用交换文件
  4. 区块链技术人才严重不足,平均薪资 2.58 万
  5. python时间处理方法_基于python时间处理方法(详解)
  6. linux在多核处理器上的负载均衡原理(2)
  7. win10 把软件窗口背景设置成豆沙绿
  8. Python + Opencv 实现遥感影像tif格式转jpg
  9. linux木马查杀工具,【Kali】linux木马查杀
  10. python实现火车票查询_python实现12306火车票查询的实例全过程
  11. 8月国内搜索引擎市场份额:360搜索上涨至18.23%
  12. 基于JAVA高铁在线购票系统计算机毕业设计源码+数据库+lw文档+系统+部署
  13. Linux终端-对NTFS文件系统数据丢失后的恢复案例
  14. Ravpower苹果20W充电器,充电快又稳,使用更安全
  15. python画三维坐标图像_由RGB-D图像获取三维坐标(相机坐标) Python
  16. 【UGUI】横向与纵向布局组件
  17. 拓扑排序(最大食物链计数、图文结合)
  18. 阿里云AliGenie开发天猫语音功能-入门篇
  19. 百度网盘下载很慢,提速设置
  20. 『统计学』第一部分:常用概率分布

热门文章

  1. SpringtBoot+SpringSecurity+Jwt+MyBatis整合实现用户认证以及权限控制
  2. python 奇偶链表
  3. python 字符串反转
  4. css设置元素继承父元素宽度_CSS设置HTML元素的高度与宽度的各种情况总结
  5. 杰奇linux伪静态,常用的13个.htaccess重写URL的伪静态规则
  6. php 类 静态调用 实例化 效率,php类的静态调用和实例化调用有哪些不同点?
  7. centos 推荐使用epel源
  8. 【自动驾驶】19.自动驾驶各个坐标系
  9. Faster R-CNN教程
  10. Java中用ClassLoader载入各种资源(类、文件、web资源)的方法