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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!