php如何实现弱类型

PHPer都知道,PHP是一门弱类型语言。所谓弱类型是指,变量在声明时不需要指明存储的数据类型。

1
2
3
4
5
6
<?php   
$var = 1; //int
$var = "laruence"; //string
$var = 1.0002; //float
$var = array(); // array
$var = new Exception('error'); //object;

那么PHP是如何实现这种弱类型变量的呢?

PHP变量的定义

注:zval在PHP7中有所优化

在PHP中,所有的变量都是用一个结构-zval来保存的, 在Zend/zend.h中我们可以看到zval的定义:

1
2
3
4
5
6
typedef struct _zval_struct {   
zvalue_value value;
zend_uint refcount;
zend_uchar type;
zend_uchar is_ref;
} zval;

问题一、Zend引擎是如何用C实现这种弱类型的呢?

其中zvalue_value是真正保存数据的关键部分,现在到了揭晓谜底的时候了,PHP是如何在ZE的基础上实现弱类型的呢? 因为zvalue_value是个联合体(union)。

1
2
3
4
5
6
7
8
9
10
typedef union _zvalue_value {   
lval;
dval;
truct {
*val;
len;
} str;
HashTable *ht;
zend_object_value obj;
} zvalue_value;

问题二、Zend引擎是如何判别、存储PHP中的多种数据类型的呢?

_zval_struct.type中存储着一个变量的真正类型,根据type来选择如何获取zvalue_value的值。

1
2
3
4
5
6
7
8
9
10
11
(Zend/zend.h)
#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

来看一个简单的例子:

1
2
3
<?php
$a = 1; //此时zval.type = IS_LONG,那么zval.value就去取lval.
$a = array(); //此时zval.type = IS_ARRAY,那么zval.value就去取ht

参考文献

  1. PHP源码分析-弱类型变量实现
  2. 深入理解PHP7内核之zval
  3. 笔记