数据结构 TString
存储一个字符串,从数据结构的角度来看 需要存储两个数据,一个是 字符串的内存地址 ,一个是字符串的长度 ,先看一下 在lobject.h中的存储字符串类型的数据结构 TString
CommonHeader : 需要进行GC的数据类型的通用头部结构
extra : 针对短字符串 ,标识当前字符串是不是lua的保留字 针对长字符串 ,标识字符串是否已经计算过hash值
shrlen: 短字符串长度
hash: 字符串的散列值, 用于字符串比较的优化
常规比较字符串是根据字符串长度进行逐位比较 时间复杂度与字符串长度线性相关 ,因为lua中字符串是被内化的数据类型 ,字符串的查找、比较操作较多 ,所以lua记录了一个散列值 ,使用散列值进行比较(性能优化)
u -> lnglen : 长字符串长度
u-> hnext :指向下一个短字符串
从上面的TString结构可以看出 ,lua源码中将字符串分为短字符串 和 长字符串 两种。有些人看了这个结构体或许会有一些疑问 ,这个结构体里怎么没有存储字符串的成员,那它怎么存字符串啊 ?? 其实英语比较好的同学已经看出来了, 这个结构上面的注释写的很清楚 (Header for string value; string bytes follow the end of this structure )大概意思就是TString结构体只是字符串类型的头,真正的字符串紧跟在这个结构体后面 ),那新的问题又出来了 ,如何从一个TString获取到它对应的字符串 ??正常情况下,想要获取一个字符串 ,需要指向字符串内存数据的指针 和 字符串的长度,字符串的长度已经在TString里了,指向字符串内存数据的指针要怎么获取呢, 这要是放在某些语言里你还真获取不到 ,但是C就不一样了,既然它说真正的字符串紧跟在这个结构体后面,假设有TString* ts , ((char*)ts+sizeof(TString))就是指向字符串的指针了 。理论上确实如此,但是在lua源码里却有一些出入,下面是根据TString *ts取字符串的源码:
上图的宏定义是lua中通过一个TString*类型的ts ,来获取对应字符串的源码 ,在没有断言的情况下,该宏定义可以简化为 #define getstr(ts) ((cha*)ts + sizeof(UTString) ) .怎么又蹦出来一个UString ? 我们来看一下UTString的定义