美文网首页
php中弱语言类型的底层实现

php中弱语言类型的底层实现

作者: 叫我峰兄 | 来源:发表于2018-07-20 10:08 被阅读0次

    php中弱语言类型的底层实现

    PHP是弱语言类型,主要分为三类:

    1、标量类型:integer、string、float、boolean

    2、复合类型:array、object

    3、特殊类型:resource、null

    php是通过c语言进行实现,但是c语言为强类型,那php的弱语言类型是如何实现的呢。

    1. 变量存储结构

    变量的值存储到以下所示zval结构体中。 zval结构体定义在Zend/zend.h文件,其结构如下:

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">typedef struct _zval_struct zval;
    ...
    struct _zval_struct {
    /* Variable information /
    zvalue_value value; /
    value /
    zend_uint refcount__gc;
    zend_uchar type; /
    active type */
    zend_uchar is_ref__gc;
    };</pre>

    PHP使用这个结构来存储变量的所有数据。和其他编译性静态语言不同, PHP在存储变量时将PHP用户空间的变量类型也保存在同一个结构体中。这样我们就能通过这些信息获取到变量的类型。

    zval结构体中有四个字段,其含义分别为:

    属性名 含义 默认值
    refcount__gc 表示引用计数 1
    is_ref__gc 表示是否为引用 0
    value 存储变量的值
    type 变量具体的类型

    2.变量类型:

    zval结构体的type字段就是实现弱类型最关键的字段了,type的值可以为: IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_ARRAY、IS_OBJECT和IS_RESOURCE 之一。 从字面上就很好理解,他们只是类型的唯一标示,根据类型的不同将不同的值存储到value字段。 除此之外,和他们定义在一起的类型还有IS_CONSTANT和IS_CONSTANT_ARRAY。

    这和我们设计数据库时的做法类似,为了避免重复设计类似的表,使用一个标示字段来记录不同类型的数据。

    二.变量的值存储

    前面提到变量的值存储在zvalue_value联合体中,结构体定义如下:

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">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;
    } zvalue_value;</pre>

    这里使用联合体而不是用结构体是出于空间利用率的考虑,因为一个变量同时只能属于一种类型。 如果使用结构体的话将会不必要的浪费空间,而PHP中的所有逻辑都围绕变量来进行的,这样的话, 内存浪费将是十分大的。这种做法成本小但收益非常大。

    各种类型的数据会使用不同的方法来进行变量值的存储,其对应赋值方式如下:

    • 一般类型
    变量类型
    boolean ZVAL_BOOL 布尔型/整型的变量值存储于(zval).value.lval中,其类型也会以相应的IS_*进行存储。

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"> Z_TYPE_P(z)=IS_BOOL/LONG; Z_LVAL_P(z)=((b)!=0); </pre>

    |
    | integer | ZVAL_LONG |
    | float | ZVAL_DOUBLE |
    | null | ZVAL_NULL | NULL值的变量值不需要存储,只需要把(zval).type标为IS_NULL。

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"> Z_TYPE_P(z)=IS_NULL; </pre>

    |
    | resource | ZVAL_RESOURCE | 资源类型的存储与其他一般变量无异,但其初始化及存取实现则不同。

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;"> Z_TYPE_P(z) = IS_RESOURCE; Z_LVAL_P(z) = l; </pre>

    |

    • 字符串String

    字符串的类型标示和其他数据类型一样,不过在存储字符串时多了一个字符串长度的字段。

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">struct {
    char *val;
    int len;
    } str;</pre>

    C中字符串是以\0结尾的字符数组,这里多存储了字符串的长度,这和我们在设计数据库时增加的冗余字段异曲同工。 因为要实时获取到字符串的长度的时间复杂度是O(n),而字符串的操作在PHP中是非常频繁的,这样能避免重复计算字符串的长度, 这能节省大量的时间,是空间换时间的做法。
    这么看在PHP中strlen()函数可以在常数时间内获取到字符串的长度。 计算机语言中字符串的操作都非常之多,所以大部分高级语言中都会存储字符串的长度。

    • 数组Array

    数组是PHP中最常用,也是最强大变量类型,它可以存储其他类型的数据,而且提供各种内置操作函数。数组的存储相对于其他变量要复杂一些, 数组的值存储在zvalue_value.ht字段中,它是一个HashTable类型的数据。 PHP的数组使用哈希表来存储关联数据。哈希表是一种高效的键值对存储结构。PHP的哈希表实现中使用了两个数据结构HashTable和Bucket。 PHP所有的工作都由哈希表实现,在下节HashTable中将进行哈希表基本概念的介绍以及PHP的哈希表实现。

    • 对象Object

    在面向对象语言中,我们能自己定义自己需要的数据类型,包括类的属性,方法等数据。而对象则是类的一个具体实现。 对象有自身的状态和所能完成的操作。

    PHP的对象是一种复合型的数据,使用一种zend_object_value的结构体来存放。其定义如下:

    <pre class="c" style="margin-top: 0px; margin-bottom: 0px; white-space: pre-wrap; word-wrap: break-word;">typedef struct _zend_object_value {
    zend_object_handle handle; // unsigned int类型,EG(objects_store).object_buckets的索引
    zend_object_handlers *handlers;
    } zend_object_value;</pre>

    PHP的对象只有在运行时才会被创建,前面的章节介绍了EG宏,这是一个全局结构体用于保存在运行时的数据。 其中就包括了用来保存所有被创建的对象的对象池,EG(objects_store),而object对象值内容的zend_object_handle域就是当前 对象在对象池中所在的索引,handlers字段则是将对象进行操作时的处理函数保存起来。 这个结构体及对象相关的类的结构_zend_class_entry,将在第五章作详细介绍。

    PHP的弱变量容器的实现方式是兼容并包的形式体现,针对每种类型的变量都有其对应的标记和存储空间。 使用强类型的语言在效率上通常会比弱类型高,因为很多信息能在运行之前就能确定,这也能帮助排除程序错误。 而这带来的问题是编写代码相对会受制约。

    相关文章

      网友评论

          本文标题:php中弱语言类型的底层实现

          本文链接:https://www.haomeiwen.com/subject/mwdfmftx.html