u=3778279685,2362934562&fm=58.jpeg

PHP类型

PHP类型基础知识

PHP是弱类型语言(依照laruence的说法是一种中强类型语言)

所谓的弱类型就是在申明一个变量的时候,并不需要显式指明它保存的数据的类型,在程序执行的过程中可以根据需求动态的改变变量的类型.

那PHP是如何实现这个功能的呢?

首先PHP定义了一个保存变量的结构体(C语言)

typedef struct _zval_struct zval;

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;
    zend_ast *ast;
} zvalue_value;

struct _zval_struct {
    /* Variable information */
    zvalue_value value;        /* value */
    zend_uint refcount__gc;   /* PHP的内存回收机制需要这个值,现在我们并不需要对它特别关注 */
    zend_uchar type;    /* active type */
    zend_uchar is_ref__gc;
};

保存变量的地方是_zvalue_value,_zvalue_value定义了一个联合体①来储存用户输入的变量

_zvalue_value可以把内存中的值相对应的解释为longdoublestr等类型,比较特殊的有三种HashTable *ht(数组)obj(对象)*ast(资源)

这个变量是什么类型由zend_uchar type; /* active type */决定,

type的种类在Zend/zend.h:583-601中定义.

/* 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中实现转换就是当zval.type = IS_LONG是,就把结构体里的value转换成long型,当zval.type = IS_STRING时,就把结构体里面的value转换成str类型

明白了以上基础知识就可以来探究zval.type会在哪些场景带来哪些问题了.


①为什么要用联合体呢?

K&R<<Pointer on C>>中我们可以翻阅到这么一段文字

联合的声明和结构类似,但它的行为方式却和结构不同.联合的所有成员引用的是内存中相同的位置.当你想在不同的时刻把不同的东西储存在同一个位置的时候,就可以使用联合.

联合体可以用来动态的表示同一个内存中的值的类型.假如使用结构体来储存用户输入地变量的话,那么假设用户输入了1,如果想要把1char,int,double等等来表示的话,就会成倍的增加内存占用.