字符串的數據結構比較簡單,牽扯到的東西比較少,我簡單展示下源碼中的數據結構的定義。
zend_string數據結構
typedef struct _zend_string zend_string; struct _zend_string { zend_refcounted_h gc; zend_ulong h; /* hash value */ size_t len; char val[1]; }; |
這個結構有4個成員。
- gc : zend_refcounted_h 結構體,主要用來變量的引用計數,用於內存管理,在後續的內存管理將會使用到
- h: 字符串的Hash Code(使用time 33 Hash算法得到的Hash值)
- len: 字符串長度
- val: 一個可變數組,用來存儲字符串內容
快速充電樁~:
- 這裏先劃重點,敲黑板啦!咱們後續的數組等複雜類型的講解,都是比較依賴HashTable來實現,使用HashTable比較重要的就是選取一個Hash函數,儘量減少Hash衝突,PHP選取實現方式Time 33算法。
- 關於Time 33算法: 目前是對於字符串Hash最好的哈希算法之一了,原因在於該算法的速度非常快,而且分類非常好(衝突小,分佈均勻).
-
由於我看的PHP源碼的版本和鳥哥不一樣,Time 33算法實現的位置也有點區別,對於有興趣的同學,我貼出對應的源碼位置
//file : zend_string.h static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len) { register zend_ulong hash = Z_UL(5381); /* variant with the hash unrolled eight times */ for (; len >= 8; len -= 8) { hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; hash = ((hash << 5) + hash) + *str++; } switch (len) { case 7: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */ case 6: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */ case 5: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */ case 4: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */ case 3: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */ case 2: hash = ((hash << 5) + hash) + *str++; /* fallthrough... */ case 1: hash = ((hash << 5) + hash) + *str++; break; case 0: break; EMPTY_SWITCH_DEFAULT_CASE() } /* Hash value can't be zero, so we always set the high bit */ #if SIZEOF_ZEND_LONG == 8 return hash | Z_UL(0x8000000000000000); #elif SIZEOF_ZEND_LONG == 4 return hash | Z_UL(0x80000000); #else # error "Unknown SIZEOF_ZEND_LONG" #endif }