zl程序教程

您现在的位置是:首页 >  硬件

当前栏目

PHP7内核基础知识之变量类型

2023-09-14 08:57:28 时间
zval结构定义

PHP7中是使用zval结构存储变量信息的。zval结构的定义在./Zend/zend_types.h文件中定义。


struct _zval_struct {

 zend_value value; /* value */

 union {

 struct {

 ZEND_ENDIAN_LOHI_4(

 zend_uchar type, /* active type */

 zend_uchar type_flags,

 zend_uchar const_flags,

 zend_uchar reserved) /* call info for EX(This) */

 } v;

 uint32_t type_info;

 } u1;

 union {

 uint32_t var_flags;

 uint32_t next; /* hash collision chain */

 uint32_t cache_slot; /* literal cache slot */

 uint32_t lineno; /* line number (for ast nodes) */

 uint32_t num_args; /* arguments number for EX(This) */

 uint32_t fe_pos; /* foreach position */

 uint32_t fe_iter_idx; /* foreach iterator index */

 } u2;

};

变量的值

通过上面的代码我们可以看到。变量是通过一个_zval_struct结构体方式存储的。其中结构体中的value存储的是变量的值。这个成员是zend_value类型的。zend_value类型的定义如下:


typedef union _zend_value {

 zend_long lval; /* long value */

 double dval; /* double value */

 zend_refcounted *counted;

 zend_string *str;

 zend_array *arr;

 zend_object *obj;

 zend_resource *res;

 zend_reference *ref;

 zend_ast_ref *ast;

 zval *zv;

 void *ptr;

 zend_class_entry *ce;

 zend_function *func;

 struct {

 uint32_t w1;

 uint32_t w2;

 } ww;

} zend_value;


zend_value是一个联合体。对于小于64位的简单类型,会直接存储值。如,long double。而对于其他比较复杂的类型,如字符串,数组,对象等,是存储的指针。这样,对于简单类型来说,变得简单高效。

获取变量类型

zval联合体的type存储的是变量的类型。PHP7已经提供了我们获取变量类型的宏方法Z_TYPE。宏方法的定义如下:


static zend_always_inline zend_uchar zval_get_type(const zval* pz) {

 return pz- u1.v.type;

#define Z_TYPE(zval) zval_get_type( (zval))

#define Z_TYPE_P(zval_p) Z_TYPE(*(zval_p))


设置变量类型

在PHP7中,设置变量类型提供了新的方法。


#define Z_TYPE_INFO(zval) (zval).u1.type_info

#define Z_TYPE_INFO_P(zval_p) Z_TYPE_INFO(*(zval_p))


代码实例

下面的代码实现了一个类似var_dump的方法。


PHP_FUNCTION(dump)

 zval *arg;

 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", arg) == FAILURE) {

 return;

 switch (Z_TYPE_P(arg)) {

 case IS_NULL:

 RETVAL_STRING("NULL");

 break;

 case IS_TRUE:

 RETVAL_STRING("true");

 break;

 case IS_FALSE:

 RETVAL_STRING("false");

 break;

 case IS_LONG:

 RETVAL_STRING("integer");

 break;

 case IS_DOUBLE:

 RETVAL_STRING("double");

 break;

 case IS_STRING:

 RETVAL_STRING("string");

 break;

 case IS_ARRAY:

 RETVAL_STRING("array");

 break;

 case IS_OBJECT:

 RETVAL_STRING("object");

 break;

 case IS_RESOURCE:

 RETVAL_STRING("resource");

 break;

 default:

 RETVAL_STRING("unknown type");