变量在 PHP7 内部的实现(二)

以下是“变量在 PHP7 内部的实现(二)”的完整攻略。

什么是变量

变量是一个可存储数据的容器,在 PHP 中我们必须先声明变量然后再给其赋值。变量名称由一个美元符号 "$" 开始,后面跟着变量的名称。

在 PHP7 中,变量的实现是通过结构体 zval 实现的。zval(Zend Value)是 PHP 变量的内部表示,所有的 PHP 值都必须使用 zval 才能在 PHP 中表示和操作。

zval 结构体

下面是 zval 结构体定义:

typedef struct _zval_struct zval;

struct _zval_struct {
    /* variable value */
    union {
        long         lval;    /* long 整型 */
        double       dval;    /* 双精度浮点型 */
        zend_refcounted *counted;
        zend_string     *str; /* 字符串 */
        zend_array      *arr; /* 数组 */
        zend_object     *obj; /* 对象 */
        zend_resource   *res; /* 资源 */
        zend_reference  *ref; /* 引用 */
        void          *ptr;
        zend_ast       *ast;
    } value;

    /* variable information */
    unsigned    int    type:3;       /* 值的类型 */
    unsigned    int    count:30;     /* 引用计数 */
    union {
        uint32_t    flags;            /* 引用计数相关的标记 */
        uint32_t    next;             /* hash chained bucket */
        uint32_t    cache_slot;       /* cache slot (for RECV_INIT) */
        uint32_t    opline_num;       /* opcode number (for _RECV_VR) */
        uint32_t    num_args;         /* arguments number for EX(This) */
        uint32_t    fe_pos;           /* foreach position */
        uint32_t    fe_iter_idx;      /* foreach iterator index */
    } u1;

    union {
        uint32_t    var_flags;        /* flags for $... */
        uint32_t    next;             /* hash chained bucket */
        uint32_t    cache_slot;       /* cache slot (for RECV_INIT) */
        uint32_t    label;            /* label position */
        uint32_t    opline_num;       /* opline number (for _DECLARE_ANON_CLASS) */
        uint32_t    num_args;         /* arguments number for EX(This) */
        uint32_t    fe_iter_idx;      /* foreach iterator index */
    } u2;
};

可以看到 zval 实际上是一个联合体,它可以代表 long, double, string, array, object, resource, reference 等多种类型。

zval 的引用计数

在 PHP 中,引用计数用于判断一个 zval 是否已经被垃圾回收,如果一个 zval 的引用计数为0,那么 PHP 核心将会回收它。因此,当我们使用一个已经被释放的 zval 时,可能会发生堆栈故障(segmentation fault)等问题。

zval 结构体中的 count 字段就是用来维护引用计数的,它的值就是指向该值的变量的数量即:可通过单一的变量声明n次来引用同一值。例如:

$a = 123;
$b = $a;
$c = &$b;

在上述 PHP 代码中,$a, $b, $c 分别是三个 zval,它们的值都是 123。同时,$b 和 $c 都是 $a 的别名(即引用)。此时,三个 zval 的引用计数都是 1。

示例说明

下面通过两个示例,来说明 PHP7 中 zval 的使用:

示例一:变量的类型转换

$x = 123;  // $x 是一个整型变量
$x = 123.0;  // $x 变成了一个浮点型变量

当我们给 zval 赋值时,PHP7 会根据变量的值来选择合适的 zval 类型。当变量的值发生改变时,PHP7 会检查该变量的类型,然后尝试将其转换为新的类型。在上述代码中,当 $x 赋值为 123 时,PHP7 会创建一个整型的 zval,当 $x 的值变为 123.0 时,在存储 $xzval 中的 type 字段被改为了浮点型类型。

示例二:foreach 循环中的引用计数自增

$arr = [1, 2, 3];
foreach ($arr as &$data) {}

在上述代码中,我们使用 foreach 循环遍历数组 $arr。由于 $data 是一个引用,因此 PHP7 内部会将 $data 的引用计数加 1。由于 $data$arr 中的一个元素,因此 PHP7 也会将该元素的引用计数加 1。这种引用计数的自增策略,能够避免在循环结束后,$data 的引用计数被错误地减 1,同时也能够避免因为在循环中修改元素值过程中,无法实时的同步更新数组元素值的问题。

在上面的两个示例中,我们可以看到 PHP7 内部是如何使用 zval 来实现变量存储和操作的,并且通过对 zval 的引用计数的维护,能够使 PHP7 能够更加高效地管理内存。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:变量在 PHP7 内部的实现(二) - Python技术站

(0)
上一篇 2023年5月25日
下一篇 2023年5月25日

相关文章

  • php微信公众号开发模式详解

    PHP微信公众号开发模式详解 前言 微信公众号已经成为了企业与用户互动的重要平台之一,为了满足企业在微信平台上的需求,我们需要了解公众号的开发模式和相关的技术方案,为此本文将从以下方面进行详细介绍: 公众号开发模式介绍 公众号开发环境搭建 公众号开发中常用的技术解析 公众号开发中常见问题与解决方案 公众号开发模式介绍 认证公众号 认证公众号是指已经通过了微信…

    PHP 2023年5月23日
    00
  • php中opendir函数用法实例

    PHP中opendir函数用法实例 1. 概述 在PHP中,opendir是用于打开目录的内建函数之一。在本篇攻略中,我们将详细介绍opendir函数的各个参数和用法,并给出两个示例说明。 2. opendir函数的语法 opendir函数的语法如下: resource opendir ( string $path [, resource $context …

    PHP 2023年5月25日
    00
  • 2010年最新PHP类的精髓归纳第2/2页

    2010年最新PHP类的精髓归纳第2/2页攻略 1. 什么是2010年最新PHP类的精髓归纳第2/2页? 这篇文章是一份对当时最新的PHP类的归纳和总结。它包含了许多有用的PHP类和函数的使用方法和示例。该攻略旨在提高开发者的PHP编程技能,同时简化代码编写流程。 2. 如何阅读和使用该攻略? 2.1 阅读操作步骤 打开网页,在页面上方可以看到目录,点击需要…

    PHP 2023年5月23日
    00
  • PHP通过iconv将字符串从GBK转换为UTF8字符集

    当我们需要在PHP代码中使用多种语言时,就需要将字符串从一种字符集(例如GBK)转换为另一种字符集(例如UTF-8)。我们可以使用PHP内置的iconv函数来完成这个任务。 以下是将字符串从GBK转换为UTF-8的步骤: 1. 构造iconv函数的参数 首先,我们需要构造iconv函数的三个参数: iconv($in_charset, $out_charse…

    PHP 2023年5月26日
    00
  • 微信小程序ibeacon三点定位详解

    微信小程序ibeacon三点定位详解攻略 什么是ibeacon? iBeacon是苹果公司于2013年发布的一项技术,它是一种短距离无线通讯技术,通过发射蓝牙信号,能够让设备在短距离内(一般为几十米)进行精确定位,它的定位范围比传统的GPS系统更加精确。与GPS相比,iBeacon的定位精度更高且不受建筑物遮挡等影响。 目前,市面上流行的iBeacon设备常…

    PHP 2023年5月30日
    00
  • php实现等比例压缩图片

    下面是详细的php实现等比例压缩图片的攻略。 一、确定图片尺寸 实现等比例压缩图片,第一步就是要确定要压缩到的尺寸。对于一个要压缩的图片,我们可以根据它的长和宽来计算它的比例。在压缩过程中,我们希望这个比例能够保持不变,这意味着长和宽都要进行按比例缩放。 我们可以通过下面的代码来计算图片在按比例缩放后的长和宽。 // $src_path:原始图片路径 // …

    PHP 2023年5月23日
    00
  • 使用 eAccelerator加速PHP代码的目的

    使用 eAccelerator 加速 PHP 代码的目的是为了提高 PHP 代码的执行效率,加快响应速度,降低服务器负载,提升网站性能。eAccelerator 是一个免费的开源 PHP 加速器,可以将 PHP 脚本编译成字节码,并对字节码进行缓存,从而避免重复编译和解释,提高 PHP 执行效率。以下是使用 eAccelerator 加速 PHP 代码的具体…

    PHP 2023年5月27日
    00
  • PHP面向对象程序设计重载(overloading)操作详解

    PHP面向对象程序设计重载(overloading)操作详解 什么是重载操作? 在 PHP 中,我们可以通过在类中定义 __call 和 __callStatic 魔术方法来实现一些特殊的操作,这就是所谓的重载操作。 所谓魔术方法,是指在 PHP 中开发人员可以自定义的,以双下划线 __ 开头的一些特殊方法。通过在类中定义这些方法,可以实现一些特殊操作,对于…

    PHP 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部