[PHP]PHP变量类型及存储结构
在2014年2月10号以前的php存储变量的结构是:
Zend/zend.h
struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc; };
在只后是在Zend/zend_types.h , 后来又进行了很多次的变更
struct _zval_struct { zend_value value; /* value */ zend_uchar type; /* active type */ union { zend_uint next; /* hash collision chain */ } u; };
这里之前的含义是:
refcount__gc 表示引用计数 1
is_ref__gc 表示是否为引用 0
value 存储变量的值
type 变量具体的类型
PHP弱类型的实现原理
zval结构体的type字段就是实现弱类型最关键的字段了,type的值可以为:IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_ARRAY、IS_OBJECT和IS_RESOURCE 之一。从字面上就很好理解,他们只是类型的唯一标示,根据类型的不同将不同的值存储到value字段。除此之外,和他们定义在一起的类型还有IS_CONSTANT和IS_CONSTANT_ARRAY。
值存在这里 , 这里14年时候也进行了变更 ,下面都是以之前的来说的:
typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; zend_ast *ast; } zvalue_value;
字符串String
字符串的类型标示和其他数据类型一样,不过在存储字符串时多了一个字符串长度的字段。
struct {
char *val;
int len;
} str;
C中字符串是以\0结尾的字符数组,这里多存储了字符串的长度,这和我们在设计数据库时增加的冗余字段异曲同工。 因为要实时获取到字符串的长度的时间复杂度是O(n),而字符串的操作在PHP中是非常频繁的,这样能避免重复计算字符串的长度, 这能节省大量的时间,是空间换时间的做法。
这么看在PHP中strlen()函数可以在常数时间内获取到字符串的长度。 计算机语言中字符串的操作都非常之多,所以大部分高级语言中都会存储字符串的长度。
数组Array
数组是PHP中最常用,也是最强大变量类型,它可以存储其他类型的数据,而且提供各种内置操作函数。数组的存储相对于其他变量要复杂一些,数组的值存储在zvalue_value.ht字段中,它是一个HashTable类型的数据。PHP的数组使用哈希表来存储关联数据。哈希表是一种高效的键值对存储结构。PHP的哈希表实现中使用了两个数据结构HashTable和Bucket。PHP所有的工作都由哈希表实现,在下节HashTable中将进行哈希表基本概念的介绍以及PHP的哈希表实现。
对象Object
在面向对象语言中,我们能自己定义自己需要的数据类型,包括类的属性,方法等数据。而对象则是类的一个具体实现。对象有自身的状态和所能完成的操作。
PHP的对象是一种复合型的数据,使用一种zend_object_value的结构体来存放。其定义如下:
typedef struct _zend_object_value { zend_object_handle handle; // unsigned int类型,EG(objects_store).object_buckets的索引 zend_object_handlers *handlers; } zend_object_value;