介绍
PHP是弱类型语言,在PHP代码中声明或使用变量的时候,并不需要强制指明其数据类型.在PHP内核中定义的变量类型:
1 | /* Zend/zend_type.h : line 304 */ |
zval
PHP底层设计了一个zval(“Zend value”的缩写)的数据结构,可以用来表示任意类型的PHP值,因此,它可能是所有PHP中最重要的结构.本节介绍zvals及其使用背后的基本概念.
1 | /* Zend/zend_type.h */ |
虽然看起来变得好大, 但其实你仔细看, 全部都是联合体, 这个新的zval在64位环境下,现在只需要16个字节(2个指针size), 它主要分为俩个部分, value和扩充字段, 而扩充字段又分为u1和u2俩个部分, 其中u1是type info, u2是各种辅助字.
其中value部分, 是一个size_t大小(一个指针大小), 可以保存一个指针, 或者一个long, 或者一个double.
而type info部分则保存了这个zval的类型. 扩充辅助字段则会在多个其他地方使用, 比如next, 就用在取代Hashtable中原来的拉链指针, 这部分会在以后介绍HashTable的时候再来详解.
从PHP7开始, 对于在zval的value字段中能保存下的值, 就不再对他们进行引用计数了, 而是在拷贝的时候直接赋值, 这样就省掉了大量的引用计数相关的操作, 这部分类型有:
IS_LONG
IS_DOUBLE
当然对于那种根本没有值, 只有类型的类型, 也不需要引用计数了:
IS_NULL
IS_FALSE
IS_TRUE
而对于复杂类型, 一个size_t保存不下的, 那么我们就用value来保存一个指针, 这个指针指向这个具体的值, 引用计数也随之作用于这个值上, 而不在是作用于zval上了.
所以, 在PHP7开始, 我们移除了MAKE_STD_ZVAL/ALLOC_ZVAL宏, 不再支持存堆内存上申请zval. 函数内部使用的zval要么来自外面输入, 要么使用在栈上分配的临时zval.
操作zval
对zval的操作定义了很多宏,这维持了一个抽象层次,使意图更清晰,将来的PHP版本zval的内部改变了还可以兼容.
1 | //不正确 |
zval.value 相关宏
1 | No. 名称 变量名 含义 访问宏 |
zval 相关宏
1 | ZVAL_UNDEF(z): 表示zval被销毁 |
在代码中查看zval
参考资料:
https://github.com/pangudashu/php7-internal/blob/master/7/var.md
https://net-newbie.com/phpext/7-zval.html
https://github.com/laruence/php7-internal/blob/master/zval.md