IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    信海龙发表于 2015-12-26 01:58:56
    love 0

    前言

    下面我们大概了解下PHP7的变量类型都有哪些,是如何存储变量的。

    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");
        }
    }
    


沪ICP备19023445号-2号
友情链接