[PHP源码阅读]array_push和array_unshift函数
在PHP中,在数组中添加元素也是一种很常用的操作,分别有在数组尾部和头部添加元素,看看PHP内部是如何实现数组插入的操作。
我在github有对PHP源码更详细的注解。感兴趣的可以围观一下,给个star。PHP5.4源码注解。可以通过commit记录查看已添加的注解。
array_push
int array_push ( array &$array , mixed $value1 [ , mixed $... ] )
array_push函数将array参数看做一个栈,将传递进来的变量压倒array的尾部。array的长度随着被压进去的变量个数增加。下面的代码有意义的效果:
$array[] = $var;
如果只需要添加一个元素到数组,使用$array[] 这种方式更好,因为这样做不用调用函数。
运行示例
$arr = array(); array_push($arr, 1, 2, 3); // return 3; $arr = [1, 2, 3]
运行步骤
array_push函数相对比较简单,就相当于压栈操作,把array看做一个栈,然后对每一个参数,让其变成引用,引用数加一,然后添加它到数组的尾部。
内部实现的流程图如下:

源码解读
添加元素使用了zend_hash_next_index_insert函数,此函数是_zend_hash_next_index_insert函数的宏定义,这个函数是PHP内部实现数组的数据结构--哈希表包含的一些API,这个API用于追加元素到哈希表或者更新哈希表中已有的哈希值。此函数实现的流程图如下:

array_unshift
int arrat_unshift ( array &$array , mixed $value1 [ , mixed $... ] )
array_unshift函数将数据元素插入到数组的头部,插入时是作为整体插入,因此后面的参数将保持同样的顺序。插入后所有的数值键名将修改为从零开始计数,所有的文字键名不变。
运行示例
$arr = array(1, 2, 3); array_unshift($arr, 4, 5, 6); // 4 5 6 1 2 3
运行步骤
1、调用php_splice将数据元素插入到数组头部,用新的哈希表替换就得哈希表并将其销毁
2、如果操作后的stack等于运行时的符号表,则重置哈希表的内部指针
3、stack指向新的哈希表,释放新的哈希表红箭,销毁就得哈希表
源码解读
由上面的步骤可知,array_unshift的核心步骤是php_splice函数。对于array_unshift函数,php_splice实现时新建一个哈希表out_hash,将需要插入的list数据先插入到out_hash中,然后再把原来的数组数据写入到out_hash中,这样实现在数组前面插入数据元素的功能。
实现的效果图如下:

小结
要理解array_push函数的执行过程主要理解栈的思想即可,而array_unshift则是新建一个数组,然后将两数组合并为结果数组。
这次阅读源码过程中,同时也研究了PHP中的哈希表数据结构及一些API,也给自己补充了一些哈希表的知识。学习到了PHP底层是使用双向链表做哈希冲突的处理,获益匪浅。日后再做关于PHP数据结构的分享。
原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
如果本文对你有帮助,请点下推荐吧,谢谢^_^
最后再安利一下,我在github有对PHP源码更详细的注解。感兴趣的可以围观一下,给个star。PHP5.4源码注解。可以通过commit记录查看已添加的注解。
更多源码文章,欢迎访问个人主页继续查看:hoohack
[PHP源码阅读]array_push和array_unshift函数的更多相关文章
- [PHP源码阅读]explode和implode函数
explode和implode函数主要用作字符串和数组间转换的操作,比如获取一段参数后根据某个字符分割字符串,或者将一个数组的结果使用一个字符合并成一个字符串输出.在PHP中经常会用到这两个函数,因此 ...
- CI框架源码阅读笔记3 全局函数Common.php
从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...
- [PHP源码阅读]array_pop和array_shift函数
上篇文章介绍了PHP添加元素到数组的函数,那么当然有从数组中删除元素.array_pop和array_shift只从数组的头或尾删除一个元素.经过阅读源码,发现这两个函数的实现都是调用了同一个函数-- ...
- [PHP源码阅读]empty和isset函数
近日被问到PHP中empty和isset函数时怎么判断变量的,刚开始我是一脸懵逼的,因为我自己也只是一知半解,为了弄懂其真正的原理,赶紧翻开源码研究研究.经过分析可发现两个函数调用的都是同一个函数,因 ...
- PHP源码阅读(一):str_split函数
注:源码版本:php5.6.33. 函数简介 str_split 原型: array str_split ( string $string [, int $split_length = 1 ] ) 说 ...
- [PHP源码阅读]array_slice和array_splice函数
array_slice和array_splice函数是用在取出数组的一段切片,array_splice还有用新的切片替换原删除切片位置的功能.类似javascript中的Array.prototype ...
- [PHP源码阅读]strtolower和strtoupper函数
字符串的操作函数中,字符串的大小写转换也算是比较常用的函数,其底层实现也比较简单,下面来一探究竟. 我在github上有对PHP源码更详细的注解.感兴趣的可以围观一下,给个star.PHP5.4源码注 ...
- ONNX Runtime 源码阅读:Graph::SetGraphInputsOutputs() 函数
目录 前言 正文 总结 前言 为了深入理解ONNX Runtime的底层机制,本文将对 Graph::SetGraphInputsOutputs() 的代码逐行分析. 正文 首先判断Graph是否从O ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...
随机推荐
- ASP.NET Aries 入门开发教程7:DataGrid的行操作(主键操作区)
前言: 抓紧勤奋,再接再励,预计共10篇来结束这个系列. 上一篇介绍:ASP.NET Aries 入门开发教程6:列表数据表格的格式化处理及行内编辑 本篇介绍主键操作区相关内容. 1:什么时候有默认的 ...
- Dapper扩展之~~~Dapper.Contrib
平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html#skill 上一篇文章:Dapper逆天入门~强类型,动态类型 ...
- HTML5 语义元素(二)文本内容
上一篇介绍的是关于页面结构方面的语义元素,本篇介绍文本内容方面,包含:<bdi>.<details>.<summary>.<mark>.<outp ...
- 为.NET Core项目定义Item Template
作为这个星球上最强大的IDE,Visual Studio不仅仅提供了很多原生的特性,更重要的是它是一个可定制的IDE,比如自定义Project Template和Item Template就是一个非常 ...
- Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验
Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...
- Struts2实现ajax的两种方式
基于Struts2框架下实现Ajax有两种方式,第一种是原声的方式,另外一种是struts2自带的一个插件. js部分调用方式是一样的: JS代码: function testAjax() { var ...
- C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”
Q: 在反序列化 Xml 字符串为 Xml 对象时,抛出如下异常. 即在 XML文档(0, 0)中有一个错误:缺少根元素. A: 首先看下代码: StringBuilder sb = new Stri ...
- JVM类加载
JVM的类加载机制就是:JVM把描述类的class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被JVM直接使用的Java类型 ClassLoader JVM中的ClassLoade ...
- webix前端架构的项目应用
webix框架兼容javascript.HTML.CSS,应用比较灵活,应用框架时,配合后台webAPI,整个web项目里面,App文件夹保存前台的多语言文件,图片文件,webix原代码js.css, ...
- Oozie分布式任务的工作流——Spark篇
Spark是现在应用最广泛的分布式计算框架,oozie支持在它的调度中执行spark.在我的日常工作中,一部分工作就是基于oozie维护好每天的spark离线任务,合理的设计工作流并分配适合的参数对于 ...