Lua中table类型源码分析

Lua中的数据结构—table
lua定义了以下几种类型:

/*
** basic types
*/
#define LUA_TNONE       (-1)

#define LUA_TNIL        0
#define LUA_TBOOLEAN        1
#define LUA_TLIGHTUSERDATA  2
#define LUA_TNUMBER     3
#define LUA_TSTRING     4
#define LUA_TTABLE      5
#define LUA_TFUNCTION       6
#define LUA_TUSERDATA       7
#define LUA_TTHREAD     8

tables的实现被分成了两个部分: 核心由ltable.c完成,提供了table的基本存取方法, 外部table库(ltablib.c)提供了辅助操作接口(concat, foreach, foreachi, getn, maxn, insert, remove, setn, sort).

ltable.c table的主要代码在这里
lobject.h lua的基础对象的定义,包括table

直接上
一.table的结构定义:

typedef struct Table {
  CommonHeader;
  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ 
  lu_byte lsizenode;  /* log2 of size of `node' array 
  */
  struct Table *metatable;
  TValue *array;  /* array part */
  Node *node;
  Node *lastfree;  /* any free position is before this position */
  GCObject *gclist;
  int sizearray;  /* size of `array' array */
} Table;

这里做几个说明:

1.其中lu_byte定义:

luatypedef unsigned char lu_byte;

2.CommonHeader:
为所有可回收资源提供标记头

#define CommonHeader    GCObject *next; lu_byte tt; lu_byte marked

3.metatable是元表,作用请自行谷歌:
struct Table *metatable;

4.TValue

typedef struct lua_TValue {
  TValuefields;
} TValue;

TValuefields:
#define TValuefields    Value value; int tt

Value:
typedef union {
  GCObject *gc;
  void *p;
  lua_Number n;
  int b;
} Value;

其实TValue是一个结构体,里面是TValuefields,它由一个宏定义完成,包括Value和一个int值。
Value是一个联合,它是里面数据类型的一种,可以是指针、数字等,这里不介绍具体用法。

5.Node

typedef union TKey {
  struct {
    TValuefields;
    struct Node *next;  /* for chaining */
  } nk;
  TValue tvk;
} TKey;

typedef struct Node {
  TValue i_val;
  TKey i_key;
} Node;

每个Node都是一个键值对。
lua之所以用这种方式来表示Node,感觉一个很重要的原因是为了适应不同参数类型的接口。
TKey中tvk是这个key的值,nk中的next则指向key冲突的下一个节点。lua的hash表的hash算法比较特别,一般的hash表都是根据key算出hash(key),然后把这个key放在hash表的hash(key)位置上,如果有冲突的话,就放在hash(key)位置的链表上。
但是lua的hash表中,如果有冲突的话,lua会找hash表中一个空的位置(从后往前找,假设为x),然后把新的key放在这个空的位置x上,并且让hash表中hash(key)处的节点的nk.next指向x。这个意思就是,假如有冲突的话,不用重新分配空间来存储冲突的key,而是利用hash表上未用过的空格来存储。但是这样会引入另外一个问题,本来key是不应该放在x的,假设有另外一个key2,hash(key2)算出来的位置也在x的话,那就表示本来x这个位置应该是给key2的,但是由于x被key占用了,导致key2没地方放了。这时候lua的处理方式是把key放到另外一个空格,然后让key2占回x。当hash表已经没有空格的时候,lua就会resize这个hash表。这样做的好处主要是不用动态申请内存空间,hash表初始化的时候有多少内存空间就用多少,不够就resize这个hash表。

小结

Created with Raphaël 2.1.0 table存储结构示意图
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值