PHP7栏目介绍相关基本变量。
变量的基础结构
我们都知道PHP的变量是弱类型的,声明的时候无需指定类型。那么这里面具体是怎么实现的呢?这就得从变量的基础结构说起了。
zval的实现
在源码文件 zend_type.h 中,可以看到 zval 的定义:
typedef struct _zval_struct 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 */ uint32_t extra; /* not further specified */ } u2; }复制代码
zval 的结构由一个保存变量类型的值或指针的 union 联合体 zend_value 以及两个 union 联合体 u1 和 u2 组成
- u1
u1的作用是用来保存变量类型及其信息,其里面的字段用处如下:
type:记录变量类型。 即可通过 u2.v.type 来访问到
type_flags:对应变量特有类型的标记(如常量类型,需引用计数类型,不可变类型),不同类型的变量对应的 flag 不一样。
const_flags:常量类型的标记
reserved:保留字段
- u2
u2 主要是辅助作用,由于结构体的内存对齐,所以 u2 的的这块空间有或者没有 u2 都是已经占据空间了,所以就利用起来。u2的辅助字段里面记录了很多类型信息,这些信息对内部功能有很大的好处,或提升缓存友好性或减少了内存寻址的操作。这里介绍其中部分字段。
next:用来解决哈希冲突问题(哈希冲突这个目前还不懂),记录冲突的下一个元素位置。
cache_slot:运行时缓存。在执行函数时会优先去缓存中查找,若缓存中没有,再去全局的 function 表中查找。
num_args:函数调用时传入参数的个数
access_flags:对象类的访问标识,如public protected private 这些。
- zend_value
typedef union _zend_value { zend_long lval; /* 整型*/ double dval; /* 浮点型 */ 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;复制代码
从 zend__value 中可以看出,long、double 类型直接存储值,而其它类型都为指针,指向各自的结构。所以,由于 zval 这样的结构,PHP 变量在声明的时候不用显示的指定其类型,因为不管你赋给变量什么类型的值,它都能帮你找到对应的存储结构。
以值为字符串的变量为例,其结构是这样的:

PHP5 与 PHP7 的 zval 结构对比
- PHP5

- PHP7

可以看到 php7 的 zval 总的只占 16 个字节,相比 PHP5 的 zval 所占用的 48 个字节节省了很大的内存。
此外,在 PHP5 中,所有的变量都在堆中申请,但是对于临时变量来说,没有必要在堆中申请。所以在 PHP7 中对此做了优化,临时变量是直接在栈中申请的。
常见变量类型
下面介绍几个常见类型的变量结构,其他更多的类型,可自行查看源码。
整型和浮点型
对于整型和浮点型,由于其占用空间小,在 zval 中是直接存储的 整型的值是存在 lval 里,浮点型值则是存储在 dval 里。
typedef union _zend_value { zend_long lval; /* 整型*/ double dval; /* 浮点型 */ ... }复制代码
字符串
PHP 7 中定义了新的字符串结构体。结构如下:
struct _zend_string { zend_refcounted_h ; zend_ulong h; /* hash value */ size_t len; char val[1]; };复制代码
上面各个字段的意思:
gc: 变量引用信息,所有用到引用计数的变量类型都会有这个结构。
h: 哈希值,数组中计算索引时会用到。(据说这个操作为 PHP7 提高了 5% 的性能)
len: 字符串长度,通过这个值保证二进制安全
val: 字符串内容,变长struct,分配时按len长度申请内存 数组
array 是 PHP 中非常强大的一个数据结构,它的底层实现就是普通的有序HashTable,这里简单看下它的结构。后续再具体深入。
typedef struct _zend_array HashTable;struct _zend_array { zend_refcounted_h gc; union { struct { ZEND_ENDIAN_LOHI_4( zend_uchar flags, zend_uchar nApplyCount, zend_uchar nIteratorsCount, zend_uchar consistency) } v; uint32_t flags; } u; uint32_t nTableMask; Bucket *arData; uint32_t nNumUsed; uint32_t nNumOfElements; uint32_t nTableSize; uint32_t nInternalPointer; zend_long nNextFreeElement; dtor_func_t pDestructor; }复制代码
###对象
PHP7 的对象结构也是重新设计了,和 PHP5 的实现有了很大的不同。
struct _zend_object { zend_refcounted_h gc; uint32_t handle; zend_class_entry *ce; const zend_object_handlers *handlers; HashTable *properties; zval properties_table[1]; };复制代码
这里介绍下其中几个字段:
gc:gc头部
*ce:对象对应的 class 类
*properties :HashTable结构,key 为对象的属性名,value 是属性值在properties_tables数组中的偏移量,通过偏移量在 properties_talbe 找到对应的属性值。
properties_talbe[1]:存储对象的属性值
免费推荐:PHP7
以上是掌握 PHP7 的基本变量的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

SublimeText3 Linux新版
SublimeText3 Linux最新版

WebStorm Mac版
好用的JavaScript开发工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

Atom编辑器mac版下载
最流行的的开源编辑器