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;