彻底搞懂 PHP 变量结构体,多数文章观点不准确

来源:互联网 发布:约战竞技场出招优化 编辑:程序博客网 时间:2024/05/17 11:32

PHP5 中的 zval

// 1. zvaltypedef struct _zval_struct {    zvalue_value value;    zend_uint refcount__gc;    zend_uchar type;    zend_uchar is_ref__gc;} zval;// 2. zvalue_valuetypedef union _zvalue_value {    long lval;     // 用于 bool 类型、整型和资源类型    double dval;    // 用于浮点类型    struct {     // 用于字符串        char *val;        int len;    } str;    HashTable *ht;    // 用于数组    zend_object_value obj;  // 用于对象    zend_ast *ast;    // 用于常量表达式(PHP5.6 才有)} zvalue_value;// 3. zend_object_valuetypedef struct _zend_object_value {    zend_object_handle handle;    const zend_object_handlers *handlers;} zend_object_value;// 4. zend_object_handletypedef unsigned int zend_object_handle;

多数文章,在提到PHP5 变量结构体的时候,都提到:sizeof(zval) == 24, sizeof(zvalue_value) == 16,实际上这个论述并不准确,在 CPU 为 64bit 时,这个结果是正确的。

但当 CPU 为32bit 时: sizeof(zval) == 16, sizeof(zvalue_value) == 8,主要因为 CPU 为 64bit 时,指针占用8个字节,而 32bit时,指针为4个字节。

PHP 7 中的 zval

// 1. zvalstruct _zval_struct {    zend_value        value;            /* value */    union {        struct {            ZEND_ENDIAN_LOHI_4(                zend_uchar    type,         /* active type */                zend_uchar    type_flags,                zend_uchar    const_flags,                zend_uchar    reserved)     /* call info for EX(This) */        } v;        uint32_t type_info;    } u1;    union {        uint32_t     next;                 /* hash collision chain */        uint32_t     cache_slot;           /* literal cache slot */        uint32_t     lineno;               /* line number (for ast nodes) */        uint32_t     num_args;             /* arguments number for EX(This) */        uint32_t     fe_pos;               /* foreach position */        uint32_t     fe_iter_idx;          /* foreach iterator index */        uint32_t     access_flags;         /* class constant access flags */        uint32_t     property_guard;       /* single property guard */    } u2;};// 2. zend_valuetypedef union _zend_value {    zend_long         lval;             /* long value */    double            dval;             /* double value */    zend_refcounted  *counted;    zend_string      *str;    zend_array       *arr;    zend_object      *obj;    zend_resource    *res;    zend_reference   *ref;    zend_ast_ref     *ast;    zval             *zv;    void             *ptr;    zend_class_entry *ce;    zend_function    *func;    struct {        uint32_t w1;        uint32_t w2;    } ww;} zend_value;

PHP 7的看似很多,但其实更简单了,不论 CPU 是32bit 还是 64bit,sizeof(zval) 永远都是等于 16。
主要看 zend_value 中的 ww,是两个 uint32_t,这个永远是 8 个字节,所以 sizeof(zend_value) == 8,因此 sizeof(zval) == 16。

所以 PHP7 新特性提到的节省内存这点上,在 32bit 系统中,PHP5 => PHP7 并无变化。

顺便说下 sizeof,不能当做函数,虽然写法像函数,这个数值会在编译期就确定好,非运行期。类似编译预处理。

有关sizeof的详情,可以看:
http://blog.csdn.net/yangtalent1206/article/details/7568541

这个CSDN 文章的排版虽然有些乱,但总结的都是精华,耐心看完,理解透彻后,就很容理解我上面的分析。

转自:http://www.yinqisen.cn/blog-781.html

原创粉丝点击