[PHP]PHP变量类型及存储结构

2020-12-31 11:20:24 浏览数 (1)

在2014年2月10号以前的php存储变量的结构是:

Zend/zend.h

代码语言:javascript复制
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 , 后来又进行了很多次的变更

代码语言:javascript复制
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年时候也进行了变更 ,下面都是以之前的来说的:

代码语言:javascript复制
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 字符串的类型标示和其他数据类型一样,不过在存储字符串时多了一个字符串长度的字段。

代码语言:javascript复制
    struct {
        char *val;
        int len;
    } str;

C中字符串是以结尾的字符数组,这里多存储了字符串的长度,这和我们在设计数据库时增加的冗余字段异曲同工。 因为要实时获取到字符串的长度的时间复杂度是O(n),而字符串的操作在PHP中是非常频繁的,这样能避免重复计算字符串的长度, 这能节省大量的时间,是空间换时间的做法。 这么看在PHP中strlen()函数可以在常数时间内获取到字符串的长度。 计算机语言中字符串的操作都非常之多,所以大部分高级语言中都会存储字符串的长度。

数组Array 数组是PHP中最常用,也是最强大变量类型,它可以存储其他类型的数据,而且提供各种内置操作函数。数组的存储相对于其他变量要复杂一些,数组的值存储在zvalue_value.ht字段中,它是一个HashTable类型的数据。PHP的数组使用哈希表来存储关联数据。哈希表是一种高效的键值对存储结构。PHP的哈希表实现中使用了两个数据结构HashTable和Bucket。PHP所有的工作都由哈希表实现,在下节HashTable中将进行哈希表基本概念的介绍以及PHP的哈希表实现。

对象Object 在面向对象语言中,我们能自己定义自己需要的数据类型,包括类的属性,方法等数据。而对象则是类的一个具体实现。对象有自身的状态和所能完成的操作。

PHP的对象是一种复合型的数据,使用一种zend_object_value的结构体来存放。其定义如下:

代码语言:javascript复制
typedef struct _zend_object_value {
    zend_object_handle handle;  // unsigned int类型,EG(objects_store).object_buckets的索引
    zend_object_handlers *handlers;
} zend_object_value;

0 人点赞