一、php变量基本特性
1、名称,变量的标示符。比如姓名标示符
2、类型 变量的类型 比如男还是女
3、值内容 具体内容 比如爱好等
二、php类型
1、php是弱类型
2、分为三类
(1)、标量类型:boolean, integer, float(double)
(2)、复合类型:array,object
(3)、特殊类型: resource, NULL
三、变量存储结构
一、变量结构
struct _zval_struct {
zvalue_value value; //存储变量的值
zend_uint refcount__gc: //引用计数,5-3之前为refcount
zend_uchar type;//变量具体的类型,IS_NULL, IS_BOOL, IS_LONG,IS_DOUBLE, IS_STRING,IS_ARRAY,IS_RESOURCE.
zend_uchar is_ref__gc; //是否为引用, 5-3之前为ref
}
二、变量值存储
1、使用联合体而不使用结构体,空间利用率的考虑,因为一个变量只是属于一中类型。
typedef union _zvalue_value {
long lval;
double dval;
struct { //C字符串以\0结尾,多存储一个长度,空间换时间
char *val;
int len;
}str;
HashTable *ht; 数据array, php哈希表实现二个数据结构HashTable 和Bucket,复杂度为o(n)
zend_object_value obj;
}zvalue_value;
2、对象Object 包括类的属性,和方法等数据
typedef struct _zend_object_value{
zend_object_handle handle; //EG(object_store).object_buckets 索引 unsigned int 类型
zend_object_handles *handles; //将对象进行操作时的处理函数保存。
}
三、哈希表(HashTable)
1、哈希表是一种通过哈希函数,将特定的键映射到特定值的一种数据结构,它维护键和值之间的对应关系。通常复杂度为O(1),哈希表为数组的扩展或者关联数组。实现文件zend/zend_hash.h 和zend/zend_hash.c
2、键(key):用户操作数据的标示,例如php数组中的索引,或者字符串键等。
3、槽(slot/bucket): 哈希表中用于保存数据的一个单元,存放的容器。
4、哈希函数(hash fuction): 将key映射(map)到数据应该存放的slot所在的位置的函数。
5、哈希冲突(hash collision):哈希函数将不同的Key映射到同一个索引的情况。
冲突解决方法:
链接法
【1】、多个KEY映射到一个槽时, 哈希表退化成一个链表,复杂度为0(n),php中的HashTable的哈希冲突就是链接法。
php的bucket实现中采用双向链表,具体结构如下:
typedef struct bucket {
ulong h; // 对char *key进行hash后的值,或者是数字的索引值
uint nKeyLength; // hash关键字长度,如果索引为数字,那么这个值为0
void *pData; // 指向用户数据(其实是数据副本,在做UPDATE_DATA或者INIT_DATA时分配了新的空间,将用户数据拷贝了一份),如果是一个指针,那么指向下面的pDataPtr
void *pDataPtr; // 如果是指针数据,那么这个值指向真正的用户数据(同上一个,也是用户数据的副本),同时上面的pData指向该值。
struct bucket *pListNext; // 指向整个hash表的下一个元素
struct bucket *pListLast; // 指向整个hash表的上一个元素
struct bucket *pNext; // 指向同一个Bucket内的下一个元素
struct bucket *pLast; // 指向同一个Bucket内的上一个元素
char arKey[1];
} Bucket;
开放寻址法
【1】、发生冲突,继续寻找下一个槽,直到找到没被占用的槽。插入和查询都是同一策略。
6、哈希表实现
【1】、实现哈希函数
【2】、冲突的解决
【3】、操作接口的实现
7、哈希表示意图