PHP7的数据类型有哪些

 PHP中变量名→zval,变量值→zend_value。其变量内存是通过引用计数管理的,在PHP7中引用计数在value结构中。

变量类型:

头文件在PHP源码 /zend/zend_types.h

PHP7的数据类型有哪些

内部实现:

PHP通过zval这个结构体来表示一个变量,而不同类型的变量值则通过zval嵌入的一个人联合体表示,即zend_value。

PHP7的数据类型有哪些

PHP7的数据类型有哪些

zend_value是一个联合体,其代码如下:

PHP7的数据类型有哪些

ast、ptr、zv这些类型只给内核自己使用。

字符串:

PHP为字符串单独定义了一个结构:zend_string。在zend_value中通过str指向具体结构。

PHP7的数据类型有哪些

PHP7的数据类型有哪些

PHP7的数据类型有哪些

存储字符串内容的val比较特殊。

val并没有使用char*类型,字符串分配时是类似这样操作的:malloc(sizeof(zend_sting)+字符串长度),就是会多分配出一些内存来存储字符串内容,这块多出来的内存起始位置就是val。

这样做的好处可以省去一次内存分配(char*),且更有助于内存管理。

val中多出来的一个字节(结构体中为val[1]而不是val[0])用于存储存储字符串的最后一个字符"\0"。

比如$a="abc",则对应的zend_string内存结构如左图:

数组:

PHP7的数据类型有哪些

PHP7的数据类型有哪些

nTableMask:这个值在散列函数根据key的hash code银蛇元素的存储为位置时用到。nTableMask = -nTableSize 或 nTableMask  = ~nTableSize+1。

nNumUsed、nNumOfElements:当删除数组元素时并不会立马从数组中删除,而是将这个元素的类型标为IS_UNDEF,只有在数组容量超限,需要扩容时才会删除。

若没有扩容,则nNumUsed将一直递增,所以其值并不是有效的元素数。nNumOfElements则是数组中有效元素的数量,所以nNumOfElements ≤ nNumUsed。

Bucket结构用力保存元素的key及value。而h是hash code:如果key是数值(及数值索引)那么它的值就是数值索引的值;如果key是字符串,那么它的值就是根据字符串key通过Time33算法计算得到的散列值。h值用来映射元素的存储位置。

PHP7的数据类型有哪些

数组实现:

为了实现散列表的有序性,PHP中的散列表在散列函数与元素数组之间加了一层映射表,这个映射表也是数组,大小与存储元素的数组相同。

中间映射表存储元素在实际存储的有序数组中的下标:元素按照先后顺序依次插入实际存储数组,然后将其数组下标按照散列函数散列出来的位置存储在新加的映射表中。

PHP7的数据类型有哪些

散列函数:根据key映射出元素的的存储位置,通常会以取模作为散列函数:key->h % nTableSize。但PHP采用另一种方式:nIndex = key->h | nTableMask。

在PHP数组的结构中并没有发现这个中间映射表,事实上,它与arData放在一起。在数组初始化时,同时分配用于存储Bucket的内存和分配相同数量的uint32_t大小的空间。然后将arData偏移到存储元素数组的位置。

中间映射表可以通过arData向前访问到。

PHP7的数据类型有哪些

哈希冲突:不同的key值可能计算得到相同的哈希值,在插入散列表时会发生冲突,因为映射表只能存储一个元素。

解决方法:把冲突的Bucket串成链表,即中间映射表映射出来的是一个Bucket链表,而不是一个Bucket,查找时需要遍历这个链表,逐个比较key,从而找到目标元素。

HashTable会记录与它冲突的元素在arData数组中的存储位置。

PHP7的数据类型有哪些

在设置映射值时,发现中间映射表中要设置的位置已经被之前插入的元素占用了(值不等于初始化的-1),那么会把已经存在的值保存到新插入的Bucket中(即c插入后u2.next=0),然后将映射表中的值更新为新Bucket的存储位置(即映射表中的值:2)。

引用:

引用是一种指向其他类型的结构,类似C语言中指针的概念。当修改引用类型的变量时,其修改将反应到实际引用的变量上。

在PHP中通过&操作符生成一个引用变量,比如$b = &$a,执行时首先为&操作的变量分配一个zend_reference结构,这个结构就是引用类型的结构体,它内嵌了一个zval,此zval的value指向原来zval的value,然后将原zval的类型修改为IS_REFERENCE,原zval的value指向新创建的zend_reference结构。

PHP7的数据类型有哪些

PHP7的数据类型有哪些

例子:

$a = date("Y-m");$b = &$a;

$a为字符串,通过&$a将其转化为引用类型并赋值给了$b,转换后的$a的类型由IS_STRING变为IS_REFERENCE,$a的value也转变为zend_reference结构,这个结构指向原来的字符串。

$a、$b间接指向了实际的value值。

PHP7的数据类型有哪些

使用引用时需要注意,引用只能通过&产生,不能通过赋值传递。

如上面的例子,再把$b赋值给其他变量,那么传递给新变量的value将是实际引用的值,而不是引用本身。

$a = date("Y-m");$b = &$a;$c = $b;   //如果想让$c也引用指向$a/$b引用的值,则:$c = &$b

PHP7的数据类型有哪些

原创文章,作者:AGZRY,如若转载,请注明出处:http://www.wangzhanshi.com/n/8809.html

(0)
AGZRY的头像AGZRY
上一篇 2025年1月1日 16:43:16
下一篇 2025年1月1日 16:46:35

相关推荐

  • 怎么在Ubuntu中支持PHP5与PHP7双版本

    1:获取PHP7源 我的操作系统版本是 Ubuntu 14.04.5 LTS,默认的PHP源是 5.5.9 版本,可以使用下列的命令确认: $ apt show…

    php 2025年1月1日
  • PHP5权威编程的示例分析

    PHP4中,不使用__construct()作为构造函数的名字,必须使用类的名字定义一个方法,就像在C++中一样。 PHP5中,使用新的统一的构造函数命名方式:__construc…

    php 2025年1月2日
  • php7与php5版本有哪些区别

                             …

    2025年1月1日
  • PHP8中的JIT是什么

    JIT 是一种编译器策略,它将代码表述为一种中间状态,在运行时将其转换为依赖于体系结构的机器码,并即时执行。在 PHP 中,这意味着 JIT 将为 Zend VM 生成的指令视为中…

    2025年1月2日
  • 怎么在Ubuntu16.04环境中安装PHP7

    由于在Ubuntu16.04上,默认的PHP版本就是7.x。由于我们要使用Apache2.4+PHP,所以安装如下模块即可直接解析PHP。 sudo apt-get&nb…

    php 2025年1月1日
  • PHP7带来了哪些新东西

    首先先来说下PHP7带来的新东西 1.类型的声明。 可以使用字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool),来声明函数的参数类型与…

    2025年1月1日
  • PHP7中的?与??有哪些区别

    php是什么语言 php,一个嵌套的缩写名称,是英文超级文本预处理语言(PHP:Hypertext Preprocessor)的缩写。PHP 是一种 HTML 内嵌式的语言,PHP…

    php 2025年1月1日
  • PHP避免SQL注入的常用方法

    在开发php网站时,经常需要和数据库交互来存储和获取数据。然而,如果不对用户输入的数据进行处理,就可能会导致SQL注入攻击。SQL注入是一种常见的安全漏洞,攻击者可以通过恶意构造的…

    php 2024年12月17日
  • PHP如何优化冗余代码

    在编程中,代码的冗余是一个常见的问题,不仅增加了代码的复杂性,还降低了可读性和可维护性。对于PHP这样的语言来说,减少代码冗余同样重要,尤其是当项目规模变得越来越大时。本文将探讨如…

    php 2024年12月17日
  • 如何解决php7+linux的规律性502错误?

    在开发测试机搭建了一套主站环境,一开始很规律的一次正常一次502, NGINX错误日志: php-fpm.log日志: php进程修改成1,strace -p pid -o tex…

    2025年1月1日

发表回复

登录后才能评论