【php7内核】数组的实现

本文深入探讨了PHP7内核中数组的实现,其底层基于散列表(HashTable)。内容包括:数组结构、散列表的特性、插入和查找机制、哈希碰撞的处理、以及扩容和重建散列表的过程。通过理解这些细节,有助于更好地掌握PHP数组的高效运作方式。
摘要由CSDN通过智能技术生成

       数组是PHP中非常强大、灵活的一种数据类型,它的底层实现为散列表(HashTable,也称作:哈希表),除了我们熟悉的PHP用户空间的Array类型之外,内核中也随处用到散列表,比如函数、类、常量、已include文件的索引表、全局符号表等都用的HashTable存储。散列表是根据关键码值(Key value)而直接进行访问的数据结构,它的key - value之间存在一个映射函数,可以根据key通过映射函数直接索引到对应的value值,它不以关键字的比较为基本操作,采用直接寻址技术(就是说,它是直接通过key映射到内存地址上去的),从而加快查找速度,在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)。

数组结构
存放记录的数组称做散列表,这个数组用来存储value,而value具体在数组中的存储位置由映射函数根据key计算确定,映射函数可以采用取模的方式,key可以通过一些譬如“times33”的算法得到一个整形值,然后与数组总大小取模得到在散列表中的存储位置。这是一个普通散列表的实现,PHP散列表的实现整体也是这个思路,只是有几个特殊的地方,下面就是PHP中HashTable的数据结构:

//Bucket:散列表中存储
typedef struct _Bucket {
	zval              val;  //存储的具体value,这里嵌入了一个zval,而不是一个指针
	zend_ulong        h;    //key根据times 33计算得到的哈希值,或者是数值索引编号
	zend_string      *key;  //存储元素的key
} Bucket;

//HashTable结构
typedef struct _zend_array HashTable;

struct _zend_array {
	zend_refcounted_h gc;
	union {
		struct {
			ZEND_ENDIAN_LOHI_4(
				zend_uchar    flags,
				zend_uchar    nApplyCount,
				zend_uchar    nIteratorsCount,
				zend_uchar    reserve)
		} v;
		uint32_t flags;
	} u;
	uint32_t          nTableMask;      //哈希值计算掩码,等于nTableSize的负值(nTableMask = -nTableSize)
	Bucket            *arData;         //存储元素数组,指向第一个Bucket
	uint32_t          nNumUsed;        //已用Bucket数
	uint32_t          nNumOfElements;  //哈希表有效元素数
	uint32_t          nTableSize;      //哈希表总大小,为2的n次方
	uint32_t          nInternalPointer;
	zend_long         nNextFreeElement;  下一个可用的数值索引,如:arr[] = 1;arr["a"] = 2;arr[] = 3;则nNextFreeElement = 2;
	dtor_func_t       pDestructor;
};

HashTable中有两个非常相近的值: nNumUsed 、 nNumOfElements ,nNumOfElements 表示哈希表已有元素数,那这个值不跟 nNumUsed 一样吗?为什么要定义两个呢?实际上它们有不同的含义,当将一个元素从哈希表删除时并不会将对应的Bucket移除,而是将Bucket存储的zval修改为 IS_UNDEF

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值