【lua学习】3.字符串

本文介绍了Lua中的字符串实现,包括全局字符串表、TString结构、luaS_newlstr的创建过程,以及字符串如何避免被回收。Lua使用散列桶结构的全局字符串表,确保同一字符串仅有一个副本,创建后不可变。新建字符串会先检查表中是否存在,通过luaS_newlstr和newlstr函数进行管理。字符串表的大小可通过luaS_resize调整,而保留字通过luaS_fix标记避免回收。
摘要由CSDN通过智能技术生成

Lua字符串的概况

  • Lua虚拟机中存在一个散列桶结构的全局字符串表来存放所有字符串
  • 关于比较字符串:先比较hash,再比较长度,再逐字符比较。节省时间
  • 同一个字符串在Lua虚拟机中仅有一个副本。节省空间
  • 一旦创建则无法变更
  • 变量存放的仅是字符串的引用

字符串实现

字符串结构TString

(lobject.h) TString

typedef union TString {
   
	L_Umaxalign dummy;//保证最大对其//见下文
	struct {
   
		CommonHeader;
		lu_byte reserved;//当>0时,其值-1表示保留字列表中的索引//见下文
		unsigned int hash;//字符串散列值,根据字符串长度和部分字符计算而来的值,见下文
		size_t len;//字符串长度
	} tsv;
} TString;

(llimits.h) L_Umaxalign

typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;//LUAI_USER_ALIGNMENT_T见下文

(luaconf.h) LUAI_USER_ALIGNMENT_T

//看此定义,为8字节对齐
#define LUAI_USER_ALIGNMENT_T union { double u; void* s; long l; }

全局字符串表stringtable

(lstate.h) stringtable

typedef struct stringtable {
   
	GCObject** hash;//开散列结构(和lua table的闭散列结构是有区别的),指向一个数组,每个元素是桶(GCObject*类型),桶管理GCObject链表
	lu_int32 nuse;//存储的字符串数量
	int size;//全局字符串表的最大容量(hash桶的最大数量)
} stringtable;

新建字符串luaS_newlstr (先查表,再决定创建与否)

(lstring.c) luaS_newlstr

TString* luaS_newlstr(lua_State* L, const char *str, size_t len)
{
   
	//初始h值就是字符串的长度
	unsigned int h = cast(unsigned int, len);//cast就是强制转型,见下文
	//获得计算hash值的跨度,如果字符串很长,若逐位计算肯定非常消耗性能
	size_t step = (len>>5) + 1;
	//从最后一个字符开始,计算h值,跟后续计算的值执行异或,进而得到最终的h值
	for (size_t l1 = len; l1 >= step; l1 -= step)
	{
   
		h ^= ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));
	}
	//h值对全局字符串表的最大桶数量求余,得到桶的索引
	unsigned int bucket_index = lmod(h, G(L)->strt.size);//lmod见下文,G见下文
	//遍历该桶管理的链表,查找有没有相等的字符串
	for (GCObject* gco = G(L)->strt.hash[bucket_index];
		gco != NULL;
		gco = gco->gch.next)
	{
   
		TString* ts = rawgco2ts(gco);//rawgco2ts见下文
		if (ts->tsv.len == len//先比较长度
			&& (memcmp(str, getstr(ts), len) == 0))//再逐位比较。getstr见下文
		{
   
			if (isdead(G(L), gco))//若要被GC,则把标记标为另一种白色,防止被GC。isdead见下文
			{
   
				changewhite(gco);
			}
			//找到了,就不需要新建了,直接返回即可
			return ts;
		}
	}
	//新建字符串
	return newlstr(L, str, len, h);
}

(llimits.h) cast宏

#define cast(t, exp) ((t)(exp))

(lobject.h) lmod宏

//针对size为2次幂的 优化的 取模算法
#define lmod(s,size) \
	(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值