php底层源码之数组

数组key和value的限制条件

 1 <?php
 2 $arr = array(
 3         1 => 'a',
 4         "1" => "b",
 5         1.5 => "c",
 6         true => "d"
 7     );
 8 var_dump($arr);
 9 
10 $arr = array(
11         "foo" => "bar",
12         "bar" => "foo",
13         100 => -100,
14         -100 => 100
15     );
16 var_dump($arr);

运行结果:
array (size=1)
1 => string 'd' (length=1)

array (size=4)
'foo' => string 'bar' (length=3)
'bar' => string 'foo' (length=3)
100 => int -100
-100 => int 100

  • ·key 可以是integer或者string
  • ·value 可以使任意类型。

key会有如下的强制转换:

  • ·包含有合法整形值得字符串会被转换为整型
  • ·浮点数和布尔值也会被转换为整型
  • ·键名null实际会被存储为“”
  • ·数组和对象不能被用为键名
  • ·相同键名,之前会被覆盖


数组内部实现:

  • ·实现数组使用了两个数据结构,一个是HashTable,另一个是bucket。
  • ·HashTable结构体用于保存整个数组需要的基本信息。
  • ·Bucket结构体用于保存具体的数据内容

 

HashTable是什么?
哈希表,是根据关键字(key value)而直接访问在内存存储位置的数据结构。也就是说,它通过把键值通过一个函数的计算,映射到保重一个位置来访问记录,这加快了查找速度。使得普通的查找和插入、杀出操作都可以在O(1)的时间内完成。这个映射函数称作哈希函数,存放记录的数组称作哈希表。

 

HashTable结构体的表示:

 1 typedef struct _hashtable {
 2     uint nTableSize;            //hash Bucket的大小,最小为8,以二倍增长
 3     uint nTableMask;            //nTableSize-1,索引取值的优化,193491849 & 127
 4     uint nNumOfElements;        //hash Bucket中当前存在的元素个数,count()函数会直接返回此值
 5     ulong nNextFreeElement;        //下一个数字索引的位置
 6     Bucket *pInternalPointer;    //当前遍历的指针,foreach比for快的原因之一,reset,current遍历函数使用
 7     Bucket *pListHead;            //存储数组头元素指针
 8     Bucket *pListTail;            //存储数组尾元素指针
 9     Bucket **arBuckets;            //存储hash数组,实际的存储容器
10     dtor_func_t pDestructor;
11     zend_bool persistent;
12     unsigned char nApplyCount;    //标记当前hash bucket被递归访问的次数(防止多次递归)
13     zend_bool bApplyProtection;
14 #if ZEND_DEBUG
15     int inconsistent;
16 #endif
17 } HashTable;

Bucket结构体:

 1 typedef struct bucket {
 2     ulong h;                        //对char *key进行hash后的值,或者使用户指定的数字索引值
 3     uint nKeyLength;                //hash关键字的长度,如果数组索引为数字,此值为0
 4     void *pData;                    //指向value,一般是用户数据的副本,如果是指针数据,则指向pDataPtr
 5     void *pDataPtr;                    //如果是指针数据,此值会指向真正的value,同时上面pData会指向此值
 6     struct bucket *pListNext;        //整个hash表的下一个元素
 7     struct bucket *pListLast;        //整个hash表表元素的上一个元素
 8     struct bucket *pNext;            //存放在同一个hash Bucket内的下一个元素
 9     struct bucket *pLast;            //同一个hash bucket的上一个元素
10     const char *arKey;                //保存当前key所对应的字符串值
11 } Bucket;

 

总结成一张图,如下:

 

posted @ 2019-08-06 15:16  独孤靖云  阅读(675)  评论(0编辑  收藏  举报