PHP7数组源码解析

PHP7数组源码解析

数组是PHP中非常强大、灵活的一种数据类型.本次分享主要介绍一下数组的底层结构;如何对数组进行查找、写入、扩容操作;以及遇到Hash冲突时是怎样巧妙处理的.

1.zval结构体

在讲它的底层实现之前,我们先了解一下变量的结构zval.(为了减少篇幅,不重要的部分用…代替)

//本文源码均基于php7.1.26
struct _zval_struct {
    zend_value        value;      
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                zend_uchar    type,     
                ...
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t     next;     
        ...
    } u2;
};

typedef union _zend_value {
    zend_long         lval;             
    double            dval;             
    zend_string      *str;
    zend_array       *arr;
    ...
} zend_value;

u1联合体中的type用来控制变量类型,类型之间的对应关系如下:

/* regular data types */
#define IS_UNDEF                    0
#define IS_NULL                     1
#define IS_FALSE                    2
#define IS_TRUE                     3
#define IS_LONG                     4
#define IS_DOUBLE                   5
#define IS_STRING                   6
#define IS_ARRAY                    7
#define IS_OBJECT                   8
#define IS_RESOURCE                 9
#define IS_REFERENCE                10

当type为7时变量类型为数组
u2联合体中的next用来解决hash冲突

2.HashTable的巧妙设计

PHP 数组的底层实现是散列表(也叫 hashTable ),散列表是根据键(Key)直接访问内存存储位置的数据结构,它的 key - value 之间存在一个映射函数,可以根据 key 通过映射函数得到的散列值直接索引到对应的 value 值,无需通过关键字比较,在理想情况下,不考虑散列冲突,散列表的查找效率是非常高的,时间复杂度是 O (1)。
从源码中我们可以看到 zend_array 的结构如下:

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    consistency)
        } v;
        uint32_t flags;
    } u;
    uint32_t          nTableMask;
    Bucket           *arData;
    uint32_t          nNumUsed;
    uint32_t          nNumOfElements;
    uint32_t          nTableSize;
    uint32_t          nInternalPointer;
    zend_long         nNextFreeElement;
    dtor_func_t       pDestructor;
};

主要字段介绍:

  • gc: 垃圾回收相关,记录了引用计数等信息.
  • nTableSize: 数组占用的长度,2的n次方(最小为8).
  • nTableMask :这个值在散列函数根据key的hash code映射元素的存储位置时用到,它的值实际就是nTableSize的负
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值