<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; HashTable</title>
	<atom:link href="https://www.phppan.com/tag/hashtable/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 04 Apr 2026 01:19:58 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>PHP源码阅读笔记二十二：array_splice函数</title>
		<link>https://www.phppan.com/2010/03/php-source-22-array_splice/</link>
		<comments>https://www.phppan.com/2010/03/php-source-22-array_splice/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 00:53:28 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=606</guid>
		<description><![CDATA[PHP源码阅读笔记二十二：array_splice函数 array_splice (PHP 4, PHP 5) [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记二十二：array_splice函数<br />
array_splice<br />
(PHP 4, PHP 5)</p>
<p>array_splice &#8212;  把数组中的一部分去掉并用其它值取代<br />
说明<br />
array array_splice ( array &#038;input, int offset [, int length [, array replacement]] )</p>
<p>array_splice() 把 input 数组中由 offset 和 length 指定的单元去掉，如果提供了 replacement 参数，则用 replacement 数组中的单元取代。返回一个包含有被移除单元的数组。注意 input 中的数字键名不被保留。 </p>
<p>如果 offset 为正，则从 input 数组中该值指定的偏移量开始移除。如果 offset 为负，则从 input 末尾倒数该值指定的偏移量开始移除。 </p>
<p>如果省略 length，则移除数组中从 offset 到结尾的所有部分。如果指定了 length 并且为正值，则移除这么多单元。如果指定了 length 并且为负值，则移除从 offset 到数组末尾倒数 length 为止中间所有的单元。小窍门：当给出了 replacement 时要移除从 offset 到数组末尾所有单元时，用 count($input) 作为 length。 </p>
<p>如果给出了 replacement 数组，则被移除的单元被此数组中的单元替代。如果 offset 和 length 的组合结果是不会移除任何值，则 replacement 数组中的单元将被插入到 offset 指定的位置。注意替换数组中的键名不保留。如果用来替换的值只是一个单元，那么不需要给它加上 array()，除非该单元本身就是一个数组</p>
<p>array_splice函数调用的是php_splice函数，对于此函数的主要代码说明如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* 创建并初始化返回数组，此返回数组为php_splice的返回数组，并非array_splice的返回数组（array_splice的返回数组为removed）*/</span>
ALLOC_HASHTABLE<span style="color: #009900;">&#40;</span>out_hash<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    
zend_hash_init<span style="color: #009900;">&#40;</span>out_hash<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> ZVAL_PTR_DTOR<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #808080; font-style: italic;">/*将数组中从开始到offset的元素拷贝到返回数组中 */</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>pos<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> p<span style="color: #339933;">=</span>in_hash<span style="color: #339933;">-&gt;</span>pListHead<span style="color: #339933;">;</span> pos<span style="color: #339933;">&lt;</span>offset <span style="color: #339933;">&amp;&amp;</span> p <span style="color: #339933;">;</span> pos<span style="color: #339933;">++,</span> p<span style="color: #339933;">=</span>p<span style="color: #339933;">-&gt;</span>pListNext<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    entry <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    entry<span style="color: #339933;">-&gt;</span>refcount<span style="color: #339933;">++;</span>
<span style="color: #808080; font-style: italic;">/*更新返回数组 */</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #009900;">&#41;</span>
    zend_hash_quick_update<span style="color: #009900;">&#40;</span>out_hash<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">else</span>
    zend_hash_next_index_insert<span style="color: #009900;">&#40;</span>out_hash<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #808080; font-style: italic;">/* 将需要移除的元素赋值给removed，即array_splice的返回数组 */</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>removed <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">;</span> pos<span style="color: #339933;">&lt;</span>offset<span style="color: #339933;">+</span>length <span style="color: #339933;">&amp;&amp;</span> p<span style="color: #339933;">;</span> pos<span style="color: #339933;">++,</span> p<span style="color: #339933;">=</span>p<span style="color: #339933;">-&gt;</span>pListNext<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    entry <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    entry<span style="color: #339933;">-&gt;</span>refcount<span style="color: #339933;">++;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #009900;">&#41;</span>
        zend_hash_quick_update<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>removed<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
        zend_hash_next_index_insert<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>removed<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #808080; font-style: italic;">/* 其它情况，跳过这些元素 */</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">;</span> pos<span style="color: #339933;">&lt;</span>offset<span style="color: #339933;">+</span>length <span style="color: #339933;">&amp;&amp;</span> p<span style="color: #339933;">;</span> pos<span style="color: #339933;">++,</span> p<span style="color: #339933;">=</span>p<span style="color: #339933;">-&gt;</span>pListNext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #808080; font-style: italic;">/* 如果有元素需要插入，即有replacement参数 */</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>list <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #808080; font-style: italic;">/* 对于每个元素，创建新的zval，拷贝并将它写入到返回数组中*/</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>list_count<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        entry <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>list<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        entry<span style="color: #339933;">-&gt;</span>refcount<span style="color: #339933;">++;</span>
        zend_hash_next_index_insert<span style="color: #009900;">&#40;</span>out_hash<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #808080; font-style: italic;">/* 拷贝剩下的元素 */</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">;</span> p <span style="color: #339933;">;</span> p<span style="color: #339933;">=</span>p<span style="color: #339933;">-&gt;</span>pListNext<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    entry <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    entry<span style="color: #339933;">-&gt;</span>refcount<span style="color: #339933;">++;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #009900;">&#41;</span>
        zend_hash_quick_update<span style="color: #009900;">&#40;</span>out_hash<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
        zend_hash_next_index_insert<span style="color: #009900;">&#40;</span>out_hash<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>entry<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* 重置数组的游标，相当于reset函数*/</span>
zend_hash_internal_pointer_reset<span style="color: #009900;">&#40;</span>out_hash<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>整个过程：<br />
1、拷贝从开始到offset的元素到返回数组<br />
2、移除从offset开始到offset＋length的元素<br />
3、如果有替换的元素，将新元素插入到offset后面的位置<br />
4、将offset+length后面的函数插入到返回数组后面<br />
5、重置数组游标<br />
<br />
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-22-array_splice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记二十一：array_slice函数</title>
		<link>https://www.phppan.com/2010/03/php-source-21-array_slice/</link>
		<comments>https://www.phppan.com/2010/03/php-source-21-array_slice/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 01:05:39 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=601</guid>
		<description><![CDATA[PHP源码阅读笔记二十一：array_slice函数 array_slice (PHP 4, PHP 5) a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记二十一：array_slice函数<br />
<strong>array_slice</strong><br />
(PHP 4, PHP 5)</p>
<p>array_slice &#8212; 从数组中取出一段<br />
说明<br />
array array_slice ( array array, int offset [, int length [, bool preserve_keys]] )</p>
<p>array_slice() 返回根据 offset 和 length 参数所指定的 array 数组中的一段序列。 </p>
<p>如果 offset 非负，则序列将从 array 中的此偏移量开始。如果 offset 为负，则序列将从 array 中距离末端这么远的地方开始。 </p>
<p>如果给出了 length 并且为正，则序列中将具有这么多的单元。如果给出了 length 并且为负，则序列将终止在距离数组末端这么远的地方。如果省略，则序列将从 offset 开始一直到 array 的末端。<br />
这一段说明在程序中的实现非常简单，如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>pos <span style="color: #339933;">&lt;</span> offset <span style="color: #339933;">+</span> length <span style="color: #339933;">&amp;&amp;</span> ...<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
.......
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>注意 array_slice() 默认将重置数组的键。自 PHP 5.0.2 起，可以通过将 preserve_keys 设为 TRUE 来改变此行为。<br />
这里所说的重置数组的键，是指重置数组中的数字键。<br />
如下所示PHP代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?PHP</span>
<span style="color: #000088;">$arr</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'s'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'s'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'0'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'ddd'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_slice</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arr</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">/*
此段程序会输出：array(4) { [0]=&gt; int(2) [1]=&gt; int(1) [&quot;s&quot;]=&gt; string(1) &quot;s&quot; [2]=&gt; string(3) &quot;ddd&quot; }
*/</span></pre></td></tr></table></div>

<p>在源码中我们可以看到：</p>
<pre lang="c" line='1"
switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &#038;string_key, &#038;string_key_len, &#038;num_key, 0, &#038;hpos)) {
    case HASH_KEY_IS_STRING:    //    key为字符串，没有重置数组键的操作
        zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, entry, sizeof(zval *), NULL);
        break;

    case HASH_KEY_IS_LONG:    //    key为数字
    if (preserve_keys) {    //    preserve_keys为true时不重置数字键
        zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, sizeof(zval *), NULL);
    } else {    //    默认情况下重置数字键
        zend_hash_next_index_insert(Z_ARRVAL_P(return_value), entry, sizeof(zval *), NULL);
    }
    break;
}

</pre>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-21-array_slice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记二十：array_flip,array_reverse函数</title>
		<link>https://www.phppan.com/2010/03/php-source-21-array_fliparray_reverse/</link>
		<comments>https://www.phppan.com/2010/03/php-source-21-array_fliparray_reverse/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 08:02:23 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=598</guid>
		<description><![CDATA[PHP源码阅读笔记二十：array_flip,array_reverse函数 array_flip (PHP  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记二十：array_flip,array_reverse函数<br />
<strong>array_flip</strong><br />
(PHP 4, PHP 5)</p>
<p>array_flip &#8212; 交换数组中的键和值<br />
说明<br />
array array_flip ( array trans )</p>
<p>array_flip() 返回一个反转后的 array，例如 trans 中的键名变成了值，而 trans 中的值成了键名。 </p>
<p>注意 trans 中的值需要能够作为合法的键名，例如需要是 integer 或者 string。如果值的类型不对将发出一个警告，并且有问题的键／值对将不会反转。 </p>
<p>如果同一个值出现了多次，则最后一个键名将作为它的值，所有其它的都丢失了。 </p>
<p>array_flip() 如果失败返回 FALSE。<br />
<strong>源码说明：遍历数组所在的Hash Table，取出key，创建一个新的ZVAL，然后以以前数组的value为key,写入返回数组的hash table中，<br />
对于以前的value，只支持LONG和STRING,如果有其它类型则警告， 对于类型的判断源码如下：</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> IS_LONG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
zend_hash_index_update<span style="color: #009900;">&#40;</span>Z_ARRVAL_P<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> Z_LVAL_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>data<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> IS_STRING<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
zend_symtable_update<span style="color: #009900;">&#40;</span>Z_ARRVAL_P<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> Z_STRVAL_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> Z_STRLEN_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>data<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
zval_ptr_dtor<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* will free also zval structure */</span>
php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Can only flip STRING and INTEGER values!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>array_reverse</strong><br />
(PHP 4, PHP 5)</p>
<p>array_reverse &#8212;  返回一个单元顺序相反的数组<br />
说明<br />
array array_reverse ( array array [, bool preserve_keys] )</p>
<p>array_reverse() 接受数组 array 作为输入并返回一个单元为相反顺序的新数组，如果 preserve_keys 为 TRUE 则保留原来的键名。<br />
<strong>源码说明：由于数组是存放在Hash Table中的，而Hash Table支持双向链表，<br />
于是程序就是从双向链表的最后一个元素开始，向前遍历，在此过程中将所有的元素复制一份（即， (*entry)->refcount++;）<br />
并将此写入返回数组所在的hash table中。</strong><br />
<br />
关于hash table中的双向链表可以查看hash table 的定义，在之前的文章有介绍：<a href="http://www.phppan.com/2009/12/php-hashtable-demo/">http://www.phppan.com/2009/12/php-hashtable-demo/</a></p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-21-array_fliparray_reverse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记十八：array_diff_key，array_diff_assoc，array_udiff_assoc 函数</title>
		<link>https://www.phppan.com/2010/03/php-source-18-array_diff_key-array_diff_assoc-array_udiff_assoc-2/</link>
		<comments>https://www.phppan.com/2010/03/php-source-18-array_diff_key-array_diff_assoc-array_udiff_assoc-2/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 00:51:42 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=585</guid>
		<description><![CDATA[PHP源码阅读笔记十八：array_diff_key，array_diff_assoc，array_udiff [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记十八：array_diff_key，array_diff_assoc，array_udiff_assoc<br />
<strong>【array_diff_key】</strong></p>
<p>(PHP 5 >= 5.1.0RC1)<br />
array_diff_key &#8212; 使用键名比较计算数组的差集<br />
说明</p>
<p>array array_diff_key ( array array1, array array2 [, array ...] )</p>
<p>array_diff_key() 返回一个数组，该数组包括了所有出现在 array1 中但是未出现在任何其它参数数组中的键名的值。注意关联关系保留不变。</p>
<p><strong>【array_diff_assoc】</strong></p>
<p>(PHP 4 >= 4.3.0, PHP 5)<br />
array_diff_assoc &#8212; 带索引检查计算数组的差集<br />
说明</p>
<p>array array_diff_assoc ( array array1, array array2 [, array ...] )</p>
<p>array_diff_assoc() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。注意和 array_diff() 不同的是键名也用于比较。</p>
<p>之所以把这三个函数放在一起是因为他们调用的最后是一个函数:php_array_diff_key<br />
<strong>【array_diff_uassoc】</strong></p>
<p>(PHP 5)<br />
array_diff_uassoc &#8212; 用用户提供的回调函数做索引检查来计算数组的差集<br />
说明</p>
<p>array array_diff_uassoc ( array array1, array array2 [, array ..., callback key_compare_func] )</p>
<p>array_diff_uassoc() 返回一个数组，该数组包括了所有在 array1 中但是不在任何其它参数数组中的值。<br />
<br />
这三个函数调用php-array_diff_key的方式如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">array_diff_key<span style="color: #339933;">:</span>         php_array_diff_key<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_COMP_DATA_NONE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
array_diff_assoc<span style="color: #339933;">:</span>      php_array_diff_key<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_COMP_DATA_INTERNAL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
array_udiff_assoc<span style="color: #339933;">:</span>    php_array_diff_key<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_COMP_DATA_USER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>其中参数的宏定义如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC</span>
&nbsp;
<span style="color: #339933;">#define DIFF_COMP_DATA_NONE    -1</span>
<span style="color: #339933;">#define DIFF_COMP_DATA_INTERNAL 0</span>
<span style="color: #339933;">#define DIFF_COMP_DATA_USER     1</span></pre></td></tr></table></div>

<p>php_array_diff_key函数首先要根据传入的data_compare_type（即上面定义的三个宏），判断所要使用的比较函数，然后遍历第一个数组，针对每一个元素与其它数组比较，看其它数字是否存在<br />
如果存在则删<br />
针对此函数的源码做一个注释性的说明：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> argc<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> IS_ARRAY<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Argument #%d is not an array&quot;</span><span style="color: #339933;">,</span> i <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            RETVAL_NULL<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">goto</span> out<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    goto语句，这个貌似一般是高手用的，嘿嘿</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    array_init<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    返回数组初始化，初始化存储此数组的Hash Table</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>p <span style="color: #339933;">=</span> Z_ARRVAL_PP<span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>pListHead<span style="color: #339933;">;</span> p <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">;</span> p <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>pListNext<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    遍历第一个参数包含的双向链表</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>nKeyLength <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    数组索引为数字</span>
            ok <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> argc<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    对其它的数组进行判断</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>zend_hash_index_find<span style="color: #009900;">&#40;</span>Z_ARRVAL_PP<span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&amp;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> SUCCESS <span style="color: #339933;">&amp;&amp;</span>
                    <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>diff_data_compare_func <span style="color: #339933;">||</span>
                     diff_data_compare_func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval<span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #339933;">,</span> data TSRMLS_CC<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    ok <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
                    <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ok<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    在第一个数组中，不在其它数组中
                <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval<span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>refcount<span style="color: #339933;">++;</span>
                zend_hash_index_update<span style="color: #009900;">&#40;</span>Z_ARRVAL_P<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>pData<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval<span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    索引为字符串</span>
            ok <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> argc<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>zend_hash_quick_find<span style="color: #009900;">&#40;</span>Z_ARRVAL_PP<span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">&amp;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> SUCCESS <span style="color: #339933;">&amp;&amp;</span>
                    <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>diff_data_compare_func <span style="color: #339933;">||</span>
                     diff_data_compare_func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval<span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #339933;">,</span> data TSRMLS_CC<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    ok <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
                    <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ok<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zval<span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>p<span style="color: #339933;">-&gt;</span>pData<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>refcount<span style="color: #339933;">++;</span>
                zend_hash_quick_update<span style="color: #009900;">&#40;</span>Z_ARRVAL_P<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>pData<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>zval<span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>关于比较函数：<br />
DIFF_COMP_DATA_NONE参数对应的是NULL,即不存在比较，使用索引查找就可以了<br />
DIFF_COMP_DATA_INTERNAL参数对应的是zval_compare，即索引和值都会比较<br />
DIFF_COMP_DATA_USER参数对应的是zval_user_compare，即用户自定义的函数<br />
<br />
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-18-array_diff_key-array_diff_assoc-array_udiff_assoc-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记十六：array_count_values函数</title>
		<link>https://www.phppan.com/2010/03/php-source-16-array_count_values/</link>
		<comments>https://www.phppan.com/2010/03/php-source-16-array_count_values/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 08:00:05 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=579</guid>
		<description><![CDATA[PHP源码阅读笔记十六：array_count_values array_count_values (PHP  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记十六：array_count_values<br />
array_count_values</p>
<p>(PHP 4, PHP 5)<br />
array_count_values &#8212; 统计数组中所有的值出现的次数<br />
说明</p>
<p>array array_count_values ( array input )</p>
<p>array_count_values() 返回一个数组，该数组用 input 数组中的值作为键名，该值在 input 数组中出现的次数作为值。</p>
<p>源程序说明：<br />
在源代码中的两句注释就说明了这个函数的实现</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">    <span style="color: #808080; font-style: italic;">/* Initialize return array */</span>
    array_init<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* Go through input array and add values to the return array */</span></pre></td></tr></table></div>

<p>但是其中还有一些细节需要注意：<br />
1、<strong>此函数只能识别字符串和数字</strong>，所以程序中使用了类似于下面的语句</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> IS_LONG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>entry<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> IS_STRING<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Can only count STRING and INTEGER values!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>2、在遍历过程中，首先判断是否不存在，此判断过程在针对字符串和数字时也有不同，但最终都是针对hash table的操作<br />
在代码中针对zval的初始化使用的是宏zval *data;    MAKE_STD_ZVAL(data);<br />
跟踪此宏的定义如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">MAKE_STD_ZVAL<span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">==&gt;</span> <span style="color: #339933;">#define MAKE_STD_ZVAL(zv)                 \    zend.h 586行</span>
    ALLOC_ZVAL<span style="color: #009900;">&#40;</span>zv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> \
    INIT_PZVAL<span style="color: #009900;">&#40;</span>zv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">==&gt;</span> <span style="color: #339933;">#define ALLOC_ZVAL(z)    \
    ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)    zend_alloc.h 165行</span>
&nbsp;
<span style="color: #339933;">==&gt;</span> <span style="color: #339933;">#define ZEND_FAST_ALLOC(p, type, fc_type)    \
    (p) = (type *) emalloc(sizeof(type))                   zend_alloc.h  152行</span>
&nbsp;
<span style="color: #339933;">==&gt;</span> <span style="color: #339933;">#define emalloc(size)                        _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)    zend_alloc.h 56行</span>
<span style="color: #339933;">==&gt;</span> ZEND_API <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>_emalloc<span style="color: #009900;">&#40;</span><span style="color: #993333;">size_t</span> size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC<span style="color: #009900;">&#41;</span>      zend_alloc.<span style="color: #202020;">c</span> <span style="color: #0000dd;">2288</span>行 程序实现
&nbsp;
<span style="color: #339933;">==&gt;</span>  <span style="color: #339933;">#define INIT_PZVAL(z)        \                 zend.h 576行</span>
    <span style="color: #009900;">&#40;</span>z<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>refcount <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>        \
    <span style="color: #009900;">&#40;</span>z<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>is_ref <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-16-array_count_values/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记十五：array_walk函数</title>
		<link>https://www.phppan.com/2010/03/php-source-15-array_walk/</link>
		<comments>https://www.phppan.com/2010/03/php-source-15-array_walk/#comments</comments>
		<pubDate>Fri, 05 Mar 2010 01:00:49 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=576</guid>
		<description><![CDATA[PHP源码阅读笔记十五：array_walk函数 array_walk (PHP 3 >= 3.0.3, PH [&#8230;]]]></description>
				<content:encoded><![CDATA[<p> PHP源码阅读笔记十五：array_walk函数</p>
<p><strong>array_walk</strong></p>
<p>(PHP 3 >= 3.0.3, PHP 4, PHP 5)<br />
array_walk &#8212; 对数组中的每个成员应用用户函数<br />
说明</p>
<p><strong>bool array_walk ( array &#038;array, callback funcname [, mixed userdata] )</strong></p>
<p>如果成功则返回 TRUE，失败则返回 FALSE。<br />
将用户自定义函数 funcname 应用到 array 数组中的每个单元。典型情况下 funcname 接受两个参数。array 参数的值作为第一个，键名作为第二个。如果提供了可选参数 userdata，将被作为第三个参数传递给 callback funcname。<br />
如果 funcname 函数需要的参数比给出的多，则每次 array_walk() 调用 funcname 时都会产生一个 E_WARNING 级的错误。这些警告可以通过在 array_walk() 调用前加上 PHP 的错误操作符 @ 来抑制，或者用 error_reporting()。<br />
    注意: 如果 funcname 需要直接作用于数组中的值，则给 funcname 的第一个参数指定为引用。这样任何对这些单元的 改变也将会改变原始数组本身。<br />
     注意: 将键名和 userdata 传递到 funcname 中是 PHP 4.0 新增加的。 </p>
<p>array_walk() 不会受到 array 内部数组指针的影响。array_walk() 会遍历整个数组而不管指针的位置。(这是由于程序在数组遍历开始时就重置了数组所在hash table的指针)<br />
用户不应在回调函数中改变该数组本身。例如增加/删除单元，unset 单元等等。如果 array_walk() 作用的数组改变了，则此函数的的行为未经定义，且不可预期。<br />
程序实现说明：<br />
扩展最后调用的是函数php_array_walk：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> php_array_walk<span style="color: #009900;">&#40;</span>HashTable <span style="color: #339933;">*</span>target_hash<span style="color: #339933;">,</span> zval <span style="color: #339933;">**</span>userdata<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> recursive TSRMLS_DC<span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>当recursive == 0时，此函数为array_walk函数实现<br />
当recursive == 1时，此函数为array_walk_recursive函数的实现<br />
源码中，程序会遍历整个数组，并针对每个数组元素，根据传入的函数，作相关的函数调用<br />
函数的调用如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">&nbsp;
    fci.<span style="color: #202020;">size</span> <span style="color: #339933;">=</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>fci<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">function_table</span> <span style="color: #339933;">=</span> EG<span style="color: #009900;">&#40;</span>function_table<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">function_name</span> <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>BG<span style="color: #009900;">&#40;</span>array_walk_func_name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">symbol_table</span> <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">object_pp</span> <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">retval_ptr_ptr</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>retval_ptr<span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">param_count</span> <span style="color: #339933;">=</span> userdata <span style="color: #339933;">?</span> <span style="color: #0000dd;">3</span> <span style="color: #339933;">:</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">params</span> <span style="color: #339933;">=</span> args<span style="color: #339933;">;</span>
            fci.<span style="color: #202020;">no_separation</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;">/* Call the userland function */</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>zend_call_function<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>fci<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>array_walk_fci_cache TSRMLS_CC<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> SUCCESS<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span></pre></td></tr></table></div>

<p>在此函数调用中有使用到一个结构体，个人添加的注释如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> _zend_fcall_info <span style="color: #009900;">&#123;</span>
 <span style="color: #993333;">size_t</span> size<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    整个结构体的长度，等于sizeof(此函数体的变量)</span>
 HashTable <span style="color: #339933;">*</span>function_table<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    executor_globals.function_table</span>
 zval <span style="color: #339933;">*</span>function_name<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    函数名 </span>
 HashTable <span style="color: #339933;">*</span>symbol_table<span style="color: #339933;">;</span>
 zval <span style="color: #339933;">**</span>retval_ptr_ptr<span style="color: #339933;">;</span>        <span style="color: #666666; font-style: italic;">//    函数的返回值</span>
 zend_uint param_count<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    参数个数</span>
 zval <span style="color: #339933;">***</span>params<span style="color: #339933;">;</span>            <span style="color: #666666; font-style: italic;">//    所调用函数的参数</span>
 zval <span style="color: #339933;">**</span>object_pp<span style="color: #339933;">;</span>        <span style="color: #666666; font-style: italic;">//    用于对象的方法调用时，存储对象</span>
 zend_bool no_separation<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    是否清空参数所在的栈</span>
<span style="color: #009900;">&#125;</span> zend_fcall_info<span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>以上为个人所注，如有错，请指正！<br />
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-15-array_walk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记十一： array_key_exists，in_array</title>
		<link>https://www.phppan.com/2010/02/php-source-11-array_key_exists%ef%bc%8cin_array/</link>
		<comments>https://www.phppan.com/2010/02/php-source-11-array_key_exists%ef%bc%8cin_array/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 14:20:37 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=542</guid>
		<description><![CDATA[PHP源码阅读笔记十一： array_key_exists，in_array array_key_exists [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记十一： array_key_exists，in_array<br />
<strong>array_key_exists</strong><br />
(PHP 4 >= 4.1.0, PHP 5)</p>
<p>array_key_exists &#8212; 检查给定的键名或索引是否存在于数组中<br />
说明<br />
<strong>bool array_key_exists ( mixed key, array search )</strong></p>
<p>array_key_exists() 在给定的 key 存在于数组中时返回 TRUE。key 可以是任何能作为数组索引的值。array_key_exists() 也可用于对象。<br />
程序会针对三种不同的类型分别处理，<br />
1、字符串： case IS_STRING:<br />
    ==> static inline int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength)<br />
    ==>#define HANDLE_NUMERIC(key, length, func) //    将处理字符串类型的key值,如果是数字则取func值所得的值，否则转下一步<br />
    ==> ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength)    //    判断在数组所在的hashtable中是否存在此字符串<br />
2、数字：case IS_LONG:<br />
    ==>ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h)    //    此函数取索引值为h的bucket，如果此索引存在多个值，则遍历取key值为数字型的bucket<br />
3、字值：case IS_NULL:<br />
    ==>zend_hash_exists(HASH_OF(*array), &#8220;&#8221;, 1)    //    判断数组所在hashtable中是否存在空值<br />
以上的函数如此存在则：RETURN_TRUE;否则：RETURN_FALSE;</p>
<p><strong>in_array</strong><br />
(PHP 4, PHP 5)</p>
<p>in_array &#8212; 检查数组中是否存在某个值<br />
说明<br />
<strong>bool in_array ( mixed needle, array haystack [, bool strict] )</strong></p>
<p>在 haystack 中搜索 needle，如果找到则返回 TRUE，否则返回 FALSE。 </p>
<p>如果第三个参数 strict 的值为 TRUE 则 in_array() 函数还会检查 needle 的类型是否和 haystack 中的相同。 </p>
<p>注意: 如果 needle 是字符串，则比较是区分大小写的。 </p>
<p>注意: 在 PHP 版本 4.2.0 之前，needle 不允许是一个数组。 </p>
<p>程序实现非常简单，遍历数组所在的hash table，依据strict选择比较函数，如果为真则使用is_identical_function，否则为is_equal_function，strict的默认值为FALSE<br />
然后使用此函数判断是否相等，如果存在则直接返回TRUE</p>
<p>但是在程序中我们有看到 target_hash = HASH_OF(*array);<br />
宏源码如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)-&gt;get_properties((p) TSRMLS_CC) : NULL)))</span></pre></td></tr></table></div>

<p>此方法的作用是判断是否是数组，如果是数组返回数组，否则判断是否是对象，如果为对象，则返回对象的所有属性，否则返回NULL<br />
但是在前面又有判断参数是否为数组的判断，如下代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>array<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> IS_ARRAY<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  php_error_docref<span style="color: #009900;">&#40;</span>NULL TSRMLS_CC<span style="color: #339933;">,</span> E_WARNING<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;Wrong datatype for second argument&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  RETURN_FALSE<span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>难道是历史遗留问题？<br />
奇怪！<br />
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/02/php-source-11-array_key_exists%ef%bc%8cin_array/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记十：array_keys,array_values函数</title>
		<link>https://www.phppan.com/2010/02/php-source-10-array_keys-array_values/</link>
		<comments>https://www.phppan.com/2010/02/php-source-10-array_keys-array_values/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 02:04:25 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Bucket]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=537</guid>
		<description><![CDATA[PHP源码阅读笔记十：array_keys,array_values函数 新年的第一篇文章，首先给各位朋友拜年 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记十：array_keys,array_values函数<br />
新年的第一篇文章，首先给各位朋友拜年<br />
今天有空看了下代码，写点东西，留作纪念！<br />
<br />
<strong>array array_keys ( array input [, mixed search_value [, bool strict]] )</strong></p>
<p>array_keys() 返回 input 数组中的数字或者字符串的键名。</p>
<p>如果指定了可选参数 search_value，则只返回该值的键名。否则 input 数组中的所有键名都会被返回。自 PHP 5 起，可以用 strict 参数来进行全等比较（===）。</p>
<p>array_keys 函数的实现在standard/array.c文件的2416行 PHP_FUNCTION(array_keys)</p>
<p>程序依照PHP一贯的风格，先判断输入是否正确，如果有第三个参数，则判断大小的函数使用is_identical_function（默认情况下是使用 is_equal_function函数）<br />
然后初始化返回的数组，遍历所给的数组，取每个元素的key值，赋值给返回的数组，这个key值又分为数字和字符串两种，其中最主要的函数是hash操作函数zend_hash_get_current_key_ex（取当前元素的key值）</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">ZEND_API <span style="color: #993333;">int</span> zend_hash_get_current_key_ex<span style="color: #009900;">&#40;</span>HashTable <span style="color: #339933;">*</span>ht<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>str_index<span style="color: #339933;">,</span> uint <span style="color: #339933;">*</span>str_length<span style="color: #339933;">,</span> ulong <span style="color: #339933;">*</span>num_index<span style="color: #339933;">,</span> zend_bool duplicate<span style="color: #339933;">,</span> HashPosition <span style="color: #339933;">*</span>pos<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    Bucket <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span>
&nbsp;
    p <span style="color: #339933;">=</span> pos <span style="color: #339933;">?</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>pos<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> ht<span style="color: #339933;">-&gt;</span>pInternalPointer<span style="color: #339933;">;</span>
&nbsp;
    IS_CONSISTENT<span style="color: #009900;">&#40;</span>ht<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    数字型的nKeyLength长度为0</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>duplicate<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #339933;">*</span>str_index <span style="color: #339933;">=</span> estrndup<span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">,</span> p<span style="color: #339933;">-&gt;</span>nKeyLength <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #339933;">*</span>str_index <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>arKey<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    /* arKey存储key名称（字符串类型的key）必须是最后一个成员，*/</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>str_length<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #339933;">*</span>str_length <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>nKeyLength<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">return</span> HASH_KEY_IS_STRING<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #339933;">*</span>num_index <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>h<span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    存储数字key值</span>
            <span style="color: #b1b100;">return</span> HASH_KEY_IS_LONG<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> HASH_KEY_NON_EXISTANT<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>对于此函数的理解主要是对bucket定义的了解</strong><br />
与bucket相关的内容请移步<a href="http://www.phppan.com/2009/12/php-hashtable-demo" target="_blank"> http://www.phppan.com/2009/12/php-hashtable-demo/</a></p>
<p>
<strong>array array_values ( array input )</strong></p>
<p>array_values() 返回 input 数组中所有的值并给其建立数字索引。<br />
array_values 函数与array_keys的函数实现基本类似，并且还少了一个zend_hash_get_current_key_ex操作和判断值类型的操作，</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/02/php-source-10-array_keys-array_values/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记九：array_unshift, array_push</title>
		<link>https://www.phppan.com/2010/02/php-source-9-array_unshift-array_push/</link>
		<comments>https://www.phppan.com/2010/02/php-source-9-array_unshift-array_push/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 05:28:56 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=530</guid>
		<description><![CDATA[今天过年了，祝各位朋友新春快乐，万事如意！ PHP源码阅读九：array_unshift, array_pus [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>今天过年了，祝各位朋友新春快乐，万事如意！</p>
<p>PHP源码阅读九：array_unshift, array_push<br />
<strong>int array_unshift ( array &#038;array, mixed var [, mixed ...] )</strong></p>
<p>array_unshift() 将传入的单元插入到 array 数组的开头。注意单元是作为整体被插入的，因此传入单元将保持同样的顺序。所有的数值键名将修改为从零开始重新计数，所有的文字键名保持不变。 </p>
<p>返回 array 数组新的单元数目。</p>
<p>在standard/array.c的2080行，可以看到此函数的C实现 PHP_FUNCTION(array_unshift)<br />
程序会先判断输入参数的个数是否正确，如果小于2则报错<br />
然后判断第一个参数是否为数组，如果不是，报错退出<br />
然后程序会调用new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &#038;args[1], argc-1, NULL);<br />
<br />
HashTable* php_splice(HashTable *in_hash, int offset, int length, zval ***list, int list_count, HashTable **removed)<br />
此函数在array.c的1861行<br />
它会先将in_hash(原来的hashtable)复制一部分到新的hashtable，这里的一部分是根据所给的offset和length来计算，array_unshif所给的offset和length都为0,所以这里不复制任何元素给新的hashtable<br />
然后遍历list，针对每个元素分别创建一个zval并使用zend_hash_next_index_insert插入到新的hashtable<br />
然后将in_hash中剩余的元素复制给新的hashtable，我们这里由于offset和length都为0，所以是全部的hashtable<br />
最后，返回新生成的hashtable<br />
<strong>整个过程就相当于先把list中的数据写入hashtable,然后把旧的数据写入hashtable，这样就实现了在数组前面插入元素</strong><br />
<br />
然后删除旧的数组所在的hashtable并刷新新HashTable，并重置hashtable的内部指针，<br />
返回hashtable中元素的个数（即新生成的数组的长度）<br />
</p>
<p><strong>int array_push ( array &#038;array, mixed var [, mixed ...] )</strong></p>
<p>array_push() 将 array 当成一个栈，并将传入的变量压入 array 的末尾。array 的长度将根据入栈变量的数目增加。<br />
和如下效果相同：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$array</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$var</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>并对每个 var 重复以上动作。 </p>
<p>返回数组新的单元总数。 </p>
<p>这个实现就比较简单了：<br />
直接遍历所给的参数，对每个元素创建一个zval，并使其引用加一，加到数组所在hashtable的后面。<br />
返回hashtable中元素的个数（即新生成的数组的长度）</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/02/php-source-9-array_unshift-array_push/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP源码阅读笔记八：array_pop, array_shift</title>
		<link>https://www.phppan.com/2010/02/php-source-8-array_pop-array_shift/</link>
		<comments>https://www.phppan.com/2010/02/php-source-8-array_pop-array_shift/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 09:27:52 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[HashTable]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=526</guid>
		<description><![CDATA[PHP源码阅读：array_pop, array_shift 要过年了，要放假了，一些事情需要收尾了，一些人也 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读：array_pop, array_shift<br />
要过年了，要放假了，一些事情需要收尾了，一些人也准备回家了，<br />
今年第一次没有回家。。。。。</p>
<p>貌似也有一个星期没有看相关的源码了，是不是上进心没有了？<br />
看样子不能因为某些原因放松对自己的要求，又买了两本书，上个月买的书才看完了一本，要加油了！。。</p>
<p>貌似说了一些废话。。。</p>
<p>在standard/array.c中我们可以找到 array_pop, array_shift这2个函数的C实现</p>
<p><strong>mixed array_pop ( array &#038;array )</strong></p>
<p>array_pop() 弹出并返回 array 数组的最后一个单元，并将数组 array 的长度减一。如果 array 为空（或者不是数组）将返回 NULL</p>
<p>注意: 使用本函数后会重置（reset()）数组指针</p>
<p><strong>mixed array_shift ( array &#038;array )</strong></p>
<p>array_shift() 将 array 的第一个单元移出并作为结果返回，将 array 的长度减一并将所有其它单元向前移动一位。所有的数字键名将改为从零开始计数，文字键名将不变。如果 array 为空（或者不是数组），则返回 NULL。 </p>
<p>注意: 使用本函数后会重置（reset()）数组指针</p>
<p>这两个函数在实现上都是使用的</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">&nbsp;
<span style="color: #808080; font-style: italic;">/* {{{ proto mixed array_pop(array stack)
   Pops an element off the end of the array */</span>
PHP_FUNCTION<span style="color: #009900;">&#40;</span>array_pop<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
 _phpi_pop<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #808080; font-style: italic;">/* }}} */</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* {{{ proto mixed array_shift(array stack)
   Pops an element off the beginning of the array */</span>
PHP_FUNCTION<span style="color: #009900;">&#40;</span>array_shift<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
 _phpi_pop<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>程序首先判断输入，然后判断数组中是否有元素，如果数组为空直接返回，<br />
如果是array_pop:<br />
    ==>zend_hash_internal_pointer_end<br />
    ==>zend_hash_internal_pointer_end_ex(ht, NULL)<br />
此时直接返回hashtable中双向链表的最后一个元素  ht->pInternalPointer = ht->pListTail;</p>
<p>如果是array_shift:<br />
    ==>zend_hash_internal_pointer_reset(Z_ARRVAL_PP(stack));<br />
    ==>zend_hash_internal_pointer_reset_ex(ht, NULL)<br />
此时直接返回hashtable中双向链表的第一个元素 ht->pInternalPointer = ht->pListHead;</p>
<p>得到返回值，通过</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">zend_hash_get_current_data 
<span style="color: #339933;">==&gt;</span> zend_hash_get_current_data_ex<span style="color: #009900;">&#40;</span>ht<span style="color: #339933;">,</span> pData<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span>
&nbsp;
 p <span style="color: #339933;">=</span> pos <span style="color: #339933;">?</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>pos<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> ht<span style="color: #339933;">-&gt;</span>pInternalPointer<span style="color: #339933;">;</span>
<span style="color: #339933;">*</span>pData <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>pData<span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>取得hashtable中的值<br />
然后删除hashtable中的这个key值，并调用zend_hash_internal_pointer_reset重置hashtable<br />
这个重置就是：ht->pInternalPointer = ht->pListHead;<br />
即把当前的位置设置为链表的第一个元素。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/02/php-source-8-array_pop-array_shift/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
