zoukankan      html  css  js  c++  java
  • 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;

    总结成一张图,如下:

  • 相关阅读:
    从0开始学FreeRTOS-(创建任务)-2
    从0开始学FreeRTOS-1
    linux(ubuntu)系统mysql-5.7 修改字符集
    腾讯云服务器简单环境配置
    linux系统ubuntu18.04安装mysql(5.7)
    ubuntu18.04从零开始配置环境(jdk+tomcat+idea)到使用idea开发web应用和servlet
    Eclipse为工具包关联源码(本例工具包为dom4j-1.6.1)
    关于c#(vs)dategridview控件继承不能修改的问题
    C语言写单链表的创建、释放、追加(即总是在最后的位置增加节点)
    c++邻接表存储图(无向),并用广度优先和深度优先遍历(实验)
  • 原文地址:https://www.cnblogs.com/lxhyty/p/11309126.html
Copyright © 2011-2022 走看看