php7 变量,变量在PHP7内部的实现(一)
(點擊上方公眾號,可快速關注我們)
英文:Nikita Popov
中文:Scholer(@Scholer-L)
鏈接:http://0x1.im/blog/php/Internal-value-representation-in-PHP-7-part-1.html
本文第一部分和第二均翻譯自Nikita Popov(nikic,PHP 官方開發組成員,柏林科技大學的學生) 的博客。為了更符合漢語的閱讀習慣,文中并不會逐字逐句的翻譯。
要理解本文,你應該對 PHP5 中變量的實現有了一些了解,本文重點在于解釋 PHP7 中 zval 的變化。
由于大量的細節描述,本文將會分成兩個部分:第一部分主要描述 zval(zend value) 的實現在 PHP5 和 PHP7 中有何不同以及引用的實現。第二部分將會分析單獨類型(strings、objects)的細節。
PHP5 中的 zval
PHP5 中 zval 結構體定義如下:
typedef struct _zval_struct {
zvalue_value value;
zend_uint refcount__gc;
zend_uchar type;
zend_uchar is_ref__gc;
} zval;
如上,zval 包含一個 value、一個 type 以及兩個 __gc 后綴的字段。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;
C 語言聯合體的特征是一次只有一個成員是有效的并且分配的內存與需要內存最多的成員匹配(也要考慮內存對齊)。所有成員都存儲在內存的同一個位置,根據需要存儲不同的值。當你需要 lval 的時候,它存儲的是有符號整形,需要 dval 時,會存儲雙精度浮點數。
需要指出的是是聯合體中當前存儲的數據類型會記錄到 type 字段,用一個整型來標記:
#define IS_NULL 0 /* Doesn't use value */
#define IS_LONG 1 /* Uses lval */
#define IS_DOUBLE 2 /* Uses dval */
#define IS_BOOL 3 /* Uses lval with values 0 and 1 */
#define IS_ARRAY 4 /* Uses ht */
#define IS_OBJECT 5 /* Uses obj */
#define IS_STRING 6 /* Uses str */
#define IS_RESOURCE 7 /* Uses lval, which is the resource ID */
/* Special types used for late-binding of constants */
#define IS_CONSTANT 8
#define IS_CONSTANT_AST 9
PHP5 中的引用計數
在PHP5中,zval 的內存是單獨從堆(heap)中分配的(有少數例外情況),PHP 需要知道哪些 zval 是正在使用的,哪些是需要釋放的。所以這就需要用到引用計數:zval 中 refcount__gc 的值用于保存 zval 本身被引用的次數,比如 $a = $b = 42 語句中,42 被兩個變量引用,所以它的引用計數就是 2。如果引用計數變成 0,就意味著這個變量已經沒有用了,內存也就可以釋放了。
注意這里提及到的引用計數指的不是 PHP 代碼中的引用(使用
Tag標簽:
總結
以上是生活随笔為你收集整理的php7 变量,变量在PHP7内部的实现(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浮点数相加php,利用php怎么实现一个
- 下一篇: php 计算月,PHP自然月的算法