php变量结构体的深入理解,彻底搞懂 PHP 变量结构体,多数文章观点不准确

### 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 的详情,可以看:

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

原文: http://www.yinqisen.cn/blog-781.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值