background image

uint nTableMask; 

/* 等于 nTableSize -1, 用于快速定位 */

 

uint nNumOfElements; 

/* HashTable 中实际元素的个数 */

 

ulong nNextFreeElement; 

/* 下个空闲可用位置的数字索引 */

 

Bucket *pInternalPointer; 

/* 内部位置指针, 会被 reset, current 这些遍历函数使用 */

 

Bucket *pListHead; 

/* 头元素, 用于线性遍历 */

 

Bucket *pListTail; 

/* 尾元素, 用于线性遍历 */

 

Bucket **arBuckets; 

/* 实际的存储容器 */

 

dtor_func_t pDestructor;

/* 元素的析构函数(指针) */

 

zend_bool persistent; 
unsigned char nApplyCount; 

/* 循环遍历保护 */

 

zend_bool bApplyProtection; 
#

if

 ZEND_DEBUG 

int inconsistent; 
#

endif

 

} HashTable; 
 
关于

nApplyCount 的意义, 我们可以通过一个例子来了解: 

代码如下

:

 
<?php 

$arr

 = 

array

(1,2,3,4,5,); 

$arr

[] = &

$arr

 
var_export(

$arr

); 

//Fatal error: Nesting level too deep - recursive dependency? 

 
这个字段就是为了防治循环引用导致的无限循环而设立的

 
查看上面的结构

, 可以看出, 对于 HashTable, 关键元素就是 arBuckets 了, 这个是实际存储的

容器

, 让我们来看看它的结构定义: 

代码如下

:

 
typedef struct bucket { 
ulong h; 

/* 数字索引/hash 值 */

 

uint nKeyLength; 

/* 字符索引的长度 */

 

void *pData; 

/* 数据 */

 

void *pDataPtr; 

/* 数据指针 */

 

struct bucket *pListNext; 

/* 下一个元素, 用于线性遍历 */

 

struct bucket *pListLast; 

/* 上一个元素, 用于线性遍历 */

 

struct bucket *pNext; 

/* 处于同一个拉链中的下一个元素 */

 

struct bucket *pLast; 

/* 处于同一拉链中的上一个元素 */

 

char arKey[1]; 

/* 节省内存,方便初始化的技巧 */

 

} Bucket;