变量存储
php的变量使用一个结构体 zval来保存的,在Zend/zend.h中我们可以看到zval的定义
struct _zval_struct { /* Variable information */ zvalue_value value; /* 变量的值 */ zend_uint refcount__gc; /* 变量被指向次数,指向一次+1 */ zend_uchar type; /* 变量当前的数据类型 */ zend_uchar is_ref__gc; /* 涉及到垃圾回收,以后补充 */ };
变量类型
1、整型/浮点/长整型/bool值
2、字符串
3、数组/关联数组
4、对象
5、资源
typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { /*字符串*/ char *val; /*值*/ int len; /*字符串长度,因为这里存储字符串长度,所以在使用 strlen函数求长度是直接返回,效率非常快*/ } str; HashTable *ht; /* hash table value PHP数组底层其实是一个hashtable */ zend_object_value obj; /*对象*/ zend_ast *ast; } zvalue_value;
底层代码变量类型定义
/* data types */ /* All data types <= IS_BOOL have their constructor/destructors skipped */ #define IS_NULL 0 #define IS_LONG 1 #define IS_DOUBLE 2 #define IS_BOOL 3 #define IS_ARRAY 4 #define IS_OBJECT 5 #define IS_STRING 6 #define IS_RESOURCE 7 #define IS_CONSTANT 8 #define IS_CONSTANT_AST 9 #define IS_CALLABLE 10 #define IS_CONSTANT_TYPE_MASK 0x00f #define IS_CONSTANT_UNQUALIFIED 0x010 #define IS_LEXICAL_VAR 0x020 #define IS_LEXICAL_REF 0x040 #define IS_CONSTANT_IN_NAMESPACE 0x100 #define IS_CONSTANT_TYPE(type) (((type) & IS_CONSTANT_TYPE_MASK) >= IS_CONSTANT && ((type) & IS_CONSTANT_TYPE_MASK) <= IS_CONSTANT_AST)
当我们在php代码中写$a = 3;
内存存储方式为:
使用xdebug_debug_zval('a');查看赋值时底层的变化
运行结果为:a: (refcount=1,is_ref=0)=3
当再赋值$b = $a;时
使用xdebug_debug_zval('a');
使用xdebug_debug_zval('b');
运行结果为:a: (refcount=2,is_ref=0)=3
b: (refcount=2,is_ref=0)=3
当再给$b赋值,$b = 5;,这个时候用到了php的特性,写时复制(Copy On Write,简称COW,因为两者有一方修改值的时候,才会进行分裂),会赋值出来一份,不使用同一个内存块。
使用xdebug_debug_zval('a');
使用xdebug_debug_zval('b');
运行结果为:
a: (refcount=1,is_ref=0)=3
b: (refcount=1,is_ref=0)=5