博客 记录生活,记录工作。

PHP源码分析(1):变量

2017-03-17
PHP

我们知道PHP是一种弱类型语言,相对于C、Java等语言来说,弱类型语言的变量能够接收各种类型的值,例如:

$var = 10;
$var = 'this is a string';
$var = array('score' => 100);
$var = new MyClass();

从上面可以看出变量$var能接整型、字符串、数组、对象等多种类型的值,非常灵活。 但是PHP是用C来实现的,C语言是强类型的语言,PHP底层是如何实现的呢?

Zend/zend.h文件中,实际定义一个变量的时候,PHP用的是zval来表示变量的,而zval又被定义为_zval_struct

typedef struct _zval_struct zval;

下面我们看_zval_struct的结构。

struct _zval_struct {
	/* Variable information */
	zvalue_value value;     /* value */
	zend_uint refcount__gc;
	zend_uchar type;    /* active type */
	zend_uchar is_ref__gc;
};

_zval_struct中,PHP除了定义存储变量的value,还存在引用计数refcount__gc、变量类型type、是否是引用is_ref__gc

PHP定义的type有以下几种,我们很容易从宏定义的名字看出来每种类型对应的值:

/* 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_ARRAY       9
#define IS_CALLABLE     10

zvalvalue字段实际保存变量的值,而value的类型是zvalue_value,结构如下:

typedef union _zvalue_value {
	long lval;                                      /* long value */
	double dval;                            /* double value */
	struct {
		char *val;
		int len;
	} str;
	HashTable *ht;                          /* hash table value */
	zend_object_value obj;  
} zvalue_value;

zvalue_value是一个union的结构,相对于struct,union能够节省更多的内存空间,降低PHP的内存占用。另外,从结构中可以看到:lval用来保存整数值;dval用来保存浮点数值;str用来指向字符串的位置并记录长度;ht用来存放一个hash表,例如数组等;obj则用来存放对象。每个变量的值都存储在这个数据结构中。

变量类型 zval.type zval.value
boolean IS_BOOL lval
integer IS_LONG lval
float IS_DOUBLE dval
null IS_NULL -
resource IS_RESOURCE lval
string IS_STRING str
array IS_ARRAY ht
object IS_OBJECT obj

每种变量的存储,以及相应存储字段如上表所示。下一节我们着重展开HashTable的分析。


评论

目录