彻底搞懂 PHP 变量结构体,多数文章观点不准确 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dawang
V2EX    PHP

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

  •  
  •   dawang 2017-10-11 16:31:00 +08:00 2622 次点击
    这是一个创建于 3003 天前的主题,其中的信息可能已经有所发展或是发生改变。
    ### PHP5 中的 zval

    ```c
    // 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; // 用于 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_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;
    ```

    多数文章,在提到 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

    ```c
    // 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 的看似很多,但其实更简单了,不论 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
    1 条回复    2017-10-28 18:16:27 +08:00
    243627152
        1
    243627152  
       2017-10-28 18:16:27 +08:00
    你这个 B 装搭好,都没人回复你了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2342 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 03:17 PVG 11:17 LAX 19:17 JFK 22:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86