Php源码学习笔记(二)
php的变量
变量的定义在 Zend/zend_types.h
下, 可以看到是由一个 zend_value 类型的 value, 还有两个联合体 u1 u2 组成的结构体。我们先说 u1 u2 再说 zend_value.
struct _zval_struct {
zend_value value; /* value */
union {
uint32_t type_info;
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type, /* active type */
zend_uchar type_flags,
union {
uint16_t extra; /* not further specified */
} u)
} v;
} u1;
union {
uint32_t next; /* hash collision chain */
uint32_t cache_slot; /* cache slot (for RECV_INIT) */
uint32_t opline_num; /* opline number (for FAST_CALL) */
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 */
uint32_t property_guard; /* single property guard */
uint32_t constant_flags; /* constant flags */
uint32_t extra; /* not further specified */
} u2;
};
u1
u1 是一个联合体, 联合体和结构体的区别就是,结构体定义了这个结构体是哪几部分组成的,联合体定义了这个联合体可能由那几个部分中的某一个组成。结构体的大小是内部各个部分大小的和,然后补齐。联合体是可能占用的最大值。
u1 比较好看,它主要包含了一个 uint32_t 类型的 type_info, 还有一个结构体,包含了两个 zend_uchar 类型的元素分别是 type 和 type_flags, 然后还有一个 uint16_t 的 extra. 这里 uint32_t 和 uint16_t 分别是 32位无符号整型 和 16位无符号整型。 我个人觉得它俩其实起到一个占空间的作用。程序运行的时候一看这个联合体有一个 uint32_t 的数,那么至少要分配一个32位的内存空间。这样就不会出现一开始声明了一个啥都没有的变量, type type_flags 都没有,没分配空间。后来要赋值了,又都有了,然后内存空间没有写不进去或者溢出的情况。 zend_uchar 其实就是 unsigned char
typedef bool zend_bool;
typedef unsigned char zend_uchar;
u2
u2 这里需要注意它是一个联合体,所以任意时刻,它的这些成员只有一个有值。 我这里推测应该是变量类型不同, u2 的存的东西也不同。 大家可以自行翻译一下注释,可以看到这里的值有可能是缓存 也可能是行号,还有可能是 foreach 时候的 key, 还有可能是访问控制修饰符。 next 是解决 hash 冲突,我在数组的章节看到这部分内容,大概意思就是两个不同的字符串 key 的 hash 值可能相同, 这种情况需要用一个双向链表把重复的内容存起来,用的时候再查找。
zend_value
理解了上面的部分, zend_value 也好理解了。需要注意的是,除了 zend_long 和 double 是直接存了值, 其他的都是存的指针。然后再注意一下占用的内存空间大小,大概是 两个 uint32_t 那么大。
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;
本作品采用《CC 协议》,转载必须注明作者和本文链接