iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >PHP是怎么存储变量的
  • 847
分享到

PHP是怎么存储变量的

2023-06-30 16:06:18 847人浏览 八月长安
摘要

本篇内容主要讲解“PHP是怎么存储变量的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php是怎么存储变量的”吧!PHP 源码中的 zval在 PHP 中定义一个变量是不需要声明类型的,一开始给

本篇内容主要讲解“PHP是怎么存储变量的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习php是怎么存储变量的”吧!

PHP 源码中的 zval

在 PHP 中定义一个变量是不需要声明类型的,一开始给变量 $a 赋予一个整型值,后面又可以轻而易举地将其改变为其他类型。那在 PHP 的源码中是如何来存储这个变量 $a 的呢?带着这个疑问我们一起去看一看 PHP 的源码。

PHP 的源码是由 C 编写的,在 PHP 的源码中使用了一个 zval 的结构体来存储在 PHP 代码中创建的变量。我们把 zval 结构体的定义拿出来简单分析一下。

这是 PHP 在 GitHub 上的官方仓库:github.com/php/php-src,本文使用的分支是 PHP-7.4.29。

zval 结构体

在 PHP 的源码中找到这个文件:php-src/Zend/zend_types.h,可以看到其中 zval 结构体的定义如下,左侧是源码。源码中使用了 PHP 自己定义的类型 zend_uchar 、uint16_t 、uint32_t 等,这些类型会针对不同平台和编译器会转为该平台下的 char short int 等。为了便于理解,我将其翻译为普通类型并展示在了源码的右侧。同时还把其中的宏函数 ZEND_ENDIAN_LOHI_3() 也展开了。

typedef struct _zval_struct zval;...       《源代码》                                               《翻译后》-------------------------------------------------------------------------------------------struct _zval_struct {                               | struct _zval_struct {    zend_value value;                               |     zend_value value;    uNIOn {                                         |     union {        struct {                                    |         struct {            ZEND_ENDIAN_LOHI_3(                     |             unsigned char type;                zend_uchar type,                    |             unsigned char type_flags;                zend_uchar type_flags,              |             union {                union {                             |                 unsigned short extra;                    uint16_t extra;                 |             } u;                } u                                 |         } v;            )                                       |         unsigned int type_info;        } v;                                        |     } u1;        uint32_t type_info;                         |     union {    } u1;                                           |         unsigned int next;    union {                                         |         unsigned int cache_slot;        uint32_t next;                              |         unsigned int opline_num;        uint32_t cache_slot;                        |         unsigned int lineno;        uint32_t opline_num;                        |         unsigned int num_args;        uint32_t lineno;                            |         unsigned int fe_pos;        uint32_t num_args;                          |         unsigned int fe_iter_idx;        uint32_t fe_pos;                            |         unsigned int access_flags;        uint32_t fe_iter_idx;                       |         unsigned int property_guard;        uint32_t access_flags;                      |         unsigned int constant_flags;        uint32_t property_guard;                    |         unsigned int extra;        uint32_t constant_flags;                    |     } u2;        uint32_t extra;                             | };    } u2;                                           |};                                                  |

在 zval 结构体中,变量的值就存储在 zend_value 类型的 value 属性中。并通过 u1.v.type 来记录这个值是什么类型的,比如 IS_LONG 对应整型,IS_STRING 对应字符串类型。

zend_value 联合体

zend_value 类型也是在 php-src/Zend/zend_types.h 中定义的,是一个联合体,下面是 zend_value 联合体的定义,左侧是源码。同样在右侧我也做了简单的翻译,把 zend_long uint32_t 翻译为普通类型便于查看。

            《源代码》                                              《翻译后》------------------------------------------------------------------------------------typedef union _zend_value {                         | typedef union _zend_value {    zend_long         lval;         |     long              lval;    double            dval;       |     double            dval;    zend_refcounted  *counted;                      |     zend_refcounted  *counted;    zend_string      *str;                          |     zend_string      *str;    zend_array       *arr;                          |     zend_array       *arr;    zend_object      *obj;                          |     zend_object      *obj;    zend_resource    *res;                          |     zend_resource    *res;    zend_reference   *ref;                          |     zend_reference   *ref;    zend_ast_ref     *ast;                          |     zend_ast_ref     *ast;    zval             *zv;                           |     zval             *zv;    void             *ptr;                          |     void             *ptr;    zend_class_entry *ce;                           |     zend_class_entry *ce;    zend_function    *func;                         |     zend_function    *func;    struct {                                        |     struct {        uint32_t w1;                                |         unsigned int w1;        uint32_t w2;                                |         unsigned int w2;    } ww;                                           |     } ww;} zend_value;                                       | } zend_value;

联合体的一个特点是其占用的内存是其属性中最大类型对应的长度。其中的 zend_long 就是 long 类型,可以看到 long 类型的 lval 和 double 类型的 dval 占用的长度都是 8 个字节。里面其他指针类型,也均为 8 个字节。最后面的结构体属性 ww 是由两个 int 型构成,长度相加也是 8 个字节。因此此联合体的长度为 8 个字节。

在我们写的 PHP 代码中,整型和浮点型数据的值会直接存放到 lval 和 dval 中。如果是字符串、数组以及其他类型时会开辟一段空间存储数据,并将其地址存放在 zend_value 中,也就是 zval.value 属性,如:zval.value.zend_long = 9527、zval.value.zend_string = 字符串地址 、zval.value.zend_array = 数组地址。然后在 zval.u1.v.type 上标记这个 zval.value 是整型、或浮点型、或字符串、或其他类型。

zval.u1.v.type 类型定义也是在 php-src/Zend/zend_types.h 文件中,全部的定义如下:

#define IS_UNDEF        0#define IS_NULL         1#define IS_FALSE        2#define IS_TRUE         3#define IS_LONG         4#define IS_DOUBLE       5#define IS_STRING       6#define IS_ARRAY        7#define IS_OBJECT       8#define IS_RESOURCE     9#define IS_REFERENCE    10#define IS_CONSTANT_AST 11#define IS_INDIRECT     13#define IS_PTR          14#define IS_ALIAS_PTR    15#define _IS_ERROR       15#define _IS_BOOL        16#define IS_CALLABLE     17#define IS_ITERABLE     18#define IS_VOID         19#define _IS_NUMBER      20

zval 结构体内存占用

接下来我们分析一下 zval 所需占用的内存。

  • value:zend_value 类型 8 个字节。

  • u1:

  • u1.v.type:unsigned char 1 个字节,u1.v.type_flags:unsigned char 1 个字节,u1.v.u:联合体中只有一个 unsigned short 的 extra 属性 2 个字节,因此 u1.v 的结构体总共是 4 个字节。

  • u1.type_info:unsigned int 4 个字节。

  • 因此 u1 这个联合体的长度取最长的属性的长度:4 个字节。

  • u2:也是一个联合体,里面都是 int 型的属性,因此长度是 4 个字节。

  • 所以 zval 总共占用的内存是 8 + 4 + 4 = 16 个字节。

也就是说当我们在写 PHP 代码时,如果创建了一个整型的变量,那么实际上它在运行中会占用 16 个字节的内存,内存开销至少是 C 语言的两倍。当然这两倍的开销也带来了 PHP 处理变量的灵活性。

到此,相信大家对“PHP是怎么存储变量的”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: PHP是怎么存储变量的

本文链接: https://www.lsjlt.com/news/330184.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PHP是怎么存储变量的
    本篇内容主要讲解“PHP是怎么存储变量的”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP是怎么存储变量的”吧!PHP 源码中的 zval在 PHP 中定义一个变量是不需要声明类型的,一开始给...
    99+
    2023-06-30
  • php怎么储存变量
    在PHP中,你可以使用变量来存储数据。要存储一个变量,你可以使用等号(=)将一个值赋给变量。例如:```$myVariable = ...
    99+
    2023-08-29
    php
  • php怎么改变变量的存储类型
    PHP是一门广泛应用于Web开发的编程语言,它的灵活性和可扩展性让开发者们能够轻松地构建各种类型的应用。在PHP中,变量存储类型的选择很重要,因为它在很大程度上影响了代码的性能和可读性。本文将介绍如何在PHP中改变变量存储类型的方法,以及它...
    99+
    2023-05-14
    php
  • php如何改变变量的存储类型
    这篇“php如何改变变量的存储类型”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“php如何改变变量的存储类型”文章吧。基础数...
    99+
    2023-07-05
  • go怎么将变量存储到内存
    在Go语言中,变量默认是存储在内存中的。当你声明一个变量时,Go会为其分配内存空间来存储变量的值。 以下是一些示例代码演示如何在Go...
    99+
    2023-10-25
    go
  • php怎么判断变量是否存在
    在PHP中,可以使用`isset()`函数来判断一个变量是否存在。`isset()`函数接受一个或多个参数,返回一个布尔值。如果所有...
    99+
    2023-08-29
    php
  • php数组可不可以储存变量
    本文小编为大家详细介绍“php数组可不可以储存变量”,内容详细,步骤清晰,细节处理妥当,希望这篇“php数组可不可以储存变量”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。php数组可以储存变量。PHP数组是一个能...
    99+
    2023-07-04
  • mysql中怎么拼接存储过程变量
    mysql中怎么拼接存储过程变量,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。存储过程变量的拼接 有时候我们需要模糊查询,但是同时我...
    99+
    2022-10-18
  • PHP变量串行化存储格式的示例分析
    这篇文章给大家分享的是有关PHP变量串行化存储格式的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。PHP还是比较常用的,于是我研究了一下PHP变量串行化,在这里拿出来和大家分享一下,希望对大家有用。串行化...
    99+
    2023-06-17
  • mysql存储过程中给变量赋值的方法是什么
    这篇文章主要介绍“mysql存储过程中给变量赋值的方法是什么”,在日常操作中,相信很多人在mysql存储过程中给变量赋值的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解...
    99+
    2022-10-19
  • mysql 在存储过程中的用户变量、系统变量、局部变量的区别
    MySQL数据库中的变量分为MySQL系统变量和MySQL用户变量。 一、MySQL用户变量:基于会话变量实现的, 可以暂存值, 并传递给同一连接里的下一条sql使用的变量.当客户端连接退出时,变量会被释放。 1、用户变量定义: 用户...
    99+
    2020-01-27
    mysql 在存储过程中的用户变量 系统变量 局部变量的区别
  • 详细谈谈JS中的内存与变量存储
    目录前言JS神奇的Number存储数字二进制如何转换why 0.1 + 0.2 !== 0.3?总结前言 在前端领域,因为大部分在跟UI打交道,内存管理是最容易被忽略的部分。...
    99+
    2022-11-12
  • JS中内存与变量存储的示例分析
    这篇文章将为大家详细讲解有关JS中内存与变量存储的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JS神奇的Number案例一:金额的计算与传递18.9 * 100=1889.9...
    99+
    2023-06-20
  • php中变量是什么
    本篇内容介绍了“php中变量是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!php中变量是用于存储信息的“容器”,与代数类似,可以给PH...
    99+
    2023-06-25
  • PHP中的可变变量是什么意思
    本篇内容主要讲解“PHP中的可变变量是什么意思”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP中的可变变量是什么意思”吧!我们学习了解了这么多关于PHP的知识,今天学习PHP中什么是可变变量...
    99+
    2023-06-20
  • C++变量存储的生命周期与作用域怎么应用
    这篇文章主要介绍“C++变量存储的生命周期与作用域怎么应用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++变量存储的生命周期与作用域怎么应用”文章能帮助大家解决问题。auto类型:非静态的局部变...
    99+
    2023-07-04
  • golang怎么用type-switch判断interface变量的实际存储类型
    这篇文章主要讲解了“golang怎么用type-switch判断interface变量的实际存储类型”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang怎么用type-switch判断...
    99+
    2023-06-30
  • php怎么判断变量是否为空
    在PHP中,可以使用`empty()`函数来判断变量是否为空。`empty()`函数会判断变量是否存在并且是否为空,如果满足这两个条...
    99+
    2023-08-25
    php
  • PHP变量怎么应用
    这篇文章主要讲解了“PHP变量怎么应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP变量怎么应用”吧!PHP 变量变量是用于存储信息的"容器":实例<...
    99+
    2023-06-04
  • php变量怎么命名
    这篇文章主要介绍“php变量怎么命名”,在日常操作中,相信很多人在php变量怎么命名问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”php变量怎么命名”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!说明变量名...
    99+
    2023-06-20
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作