Thoroughly understand PHP variable structure, most articles have inaccurate views

zvals in PHP5

 

// 1. zval
typedef struct _zval_struct {
    zvalue_value value;
    zend_uint refcount__gc;
    zend_uchar type;
    zend_uchar is_ref__gc;
} zval;

// 2. zvalue_value
typedef union _zvalue_value {
    long lval; // for bool, int and resource types
    double dval; // for floating point types
    struct { // for strings
        char * val;
        int len;
    } str;
    HashTable *ht; // for arrays
    zend_object_value obj; // for object
    zend_ast *ast; // for constant expressions (only available in PHP 5.6)
} zvalue_value;

// 3. zend_object_value
typedef struct _zend_object_value {
    zend_object_handle handle;
    const zend_object_handlers *handlers;
} zend_object_value;

// 4. zend_object_handle
typedef unsigned int zend_object_handle;

 Most articles, when referring to the PHP5 variable structure, all mention: sizeof(zval) == 24, sizeof(zvalue_value) == 16, in fact, this discussion is not accurate, when the CPU is 64bit, the result is correct.

 

 

But when the CPU is 32bit:  sizeof(zval) == 16, sizeof(zvalue_value) == 8, mainly because when the CPU is 64bit, the pointer occupies 8 bytes, and when it is 32bit, the pointer is 4 bytes.

zvals in PHP 7

 

// 1. zval
struct _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_value
typedef 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 seems to be a lot, but it is actually simpler, no matter whether the CPU is 32bit or 64bit, sizeof(zval) is always equal to 16.

 

Mainly look at ww in zend_value, which are two uint32_t, this is always 8 bytes, so sizeof(zend_value) == 8, so sizeof(zval) == 16.

Therefore, in terms of saving memory mentioned by the new features of PHP7, in 32bit systems, PHP5 => PHP7 has not changed.

By the way, sizeof cannot be used as a function. Although it is written like a function, this value will be determined at compile time, not at runtime. Similar to compilation preprocessing.

 

For more information on sizeof, see:

http://blog.csdn.net/yangtalent1206/article/details/7568541

 

Although the layout of this CSDN article is a bit messy, it summarizes the essence. After reading it patiently and thoroughly, it is easy to understand my analysis above.

 

Reprinted from: http://www.yinqisen.cn/blog-781.html

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326429516&siteId=291194637