<?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; PHP数组</title>
	<atom:link href="https://www.phppan.com/tag/php%e6%95%b0%e7%bb%84/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +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 源码阅读笔记二十五：next,current,key函数</title>
		<link>https://www.phppan.com/2010/04/php-source-25-next-current-key/</link>
		<comments>https://www.phppan.com/2010/04/php-source-25-next-current-key/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 04:16:36 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=664</guid>
		<description><![CDATA[PHP 源码阅读笔记二十五：next,current,key函数 key &#8212; 从关联数组中取得键名 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP 源码阅读笔记二十五：next,current,key函数<br />
key &#8212; 从关联数组中取得键名<br />
mixed key ( array &#038;array )<br />
key() 返回数组中当前单元的键名。<br />
<br />
此函数通过调用zend_hash.c中的zend_hash_get_current_key_ex实现key值的返回<br />
在zend_hash_get_current_key_ex函数中根据nKeyLength属性判断key为字符串或者数字，然后返回<br />
</p>
<p>current &#8212; 返回数组中的当前单元<br />
mixed current ( array &#038;array )<br />
每个数组中都有一个内部的指针指向它“当前的”单元，初始指向插入到数组中的第一个单元。<br />
current() 函数返回当前被内部指针指向的数组单元的值，并不移动指针。如果内部指针指向超出了单元列表的末端，current() 返回 FALSE。<br />
<br />
此函数通过最终是调用zend_hash_get_current_data_ex函数实现value的返回<br />
zend_hash_get_current_data_ex函数直接返回数组元素中存储的值：<br />
*pData = p->pData;<br />
如果数组中存在false元素，则返回值和没有找到的返回值是一样的，这是一个比较纠结的地方<br />
</p>
<p>next &#8212;  将数组中的内部指针向前移动一位<br />
mixed next ( array &#038;array )<br />
返回数组内部指针指向的下一个单元的值，或当没有更多单元时返回 FALSE。<br />
<br />
next() 和 current() 操作十分类似，只有一点区别，在返回值之前将内部指针向前移动一位。即调用了zend_hash_move_forward(target_hash);<br />
这意味着它返回的是下一个数组单元的值并将数组指针向前移动了一位。如果移动指针的结果是超出了数组单元的末端，则 next() 返回 FALSE。<br />
并且和current()一样，当数组元素中存在false时，next()的返回值也会是false<br />
<br />
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/04/php-source-25-next-current-key/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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_file,range函</title>
		<link>https://www.phppan.com/2010/03/php-source-19-array_file-range/</link>
		<comments>https://www.phppan.com/2010/03/php-source-19-array_file-range/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 05:17:31 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=595</guid>
		<description><![CDATA[PHP源码阅读笔记十九：array_file,range函数 array_fill (PHP 4 >= 4.2 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记十九：array_file,range函数<br />
<strong>array_fill</strong><br />
(PHP 4 >= 4.2.0, PHP 5)</p>
<p>array_fill &#8212; 用给定的值填充数组<br />
说明<br />
<strong>array array_fill ( int start_index, int num, mixed value )</strong></p>
<p>array_fill() 用 value 参数的值将一个数组填充 num 个条目，键名由 start_index 参数指定的开始。注意 num 必须是一个大于零的数值，否则 PHP 会发出一条警告。 </p>
<p>对于参数start_index，只能是字符串，整形，浮点型<br />
其源码如下：</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;">switch</span> <span style="color: #009900;">&#40;</span>Z_TYPE_PP<span style="color: #009900;">&#40;</span>start_key<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #b1b100;">case</span> IS_STRING<span style="color: #339933;">:</span>
<span style="color: #b1b100;">case</span> IS_LONG<span style="color: #339933;">:</span>
<span style="color: #b1b100;">case</span> IS_DOUBLE<span style="color: #339933;">:</span>
    .......
    <span style="color: #202020;">convert_to_long_ex</span><span style="color: #009900;">&#40;</span>start_key<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ......
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>程序首先赋值给return_value第一个值，然后循环num &#8211; 1次: <strong>给这个值添加refcount,并将它添加到return_value的Hash Table中</strong></p>
<p><strong>range</strong><br />
(PHP 3 >= 3.0.8, PHP 4, PHP 5)</p>
<p>range &#8212;  建立一个包含指定范围单元的数组<br />
说明<br />
<strong>array range ( mixed low, mixed high [, number step] )</strong></p>
<p>range() 返回数组中从 low 到 high 的单元，包括它们本身。如果 low > high，则序列将从 high 到 low。 </p>
<p>新参数: 可选的 step 参数是 PHP 5.0.0 新加的。 </p>
<p>如果给出了 step 的值，它将被作为单元之间的步进值。step 应该为正值。如果未指定，step 则默认为 1。</p>
<p>从代码可以看出，本函数仅支持字符数组，浮点数组和整形数组，并且支持递增和递减两种形式（在版本4.0.1之后才有）<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
43
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_TYPE_P<span style="color: #009900;">&#40;</span>zlow<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> IS_STRING <span style="color: #339933;">&amp;&amp;</span> Z_TYPE_P<span style="color: #009900;">&#40;</span>zhigh<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> IS_STRING <span style="color: #339933;">&amp;&amp;</span> Z_STRLEN_P<span style="color: #009900;">&#40;</span>zlow<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">1</span> <span style="color: #339933;">&amp;&amp;</span> Z_STRLEN_P<span style="color: #009900;">&#40;</span>zhigh<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> type1<span style="color: #339933;">,</span> type2<span style="color: #339933;">;</span>
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>low<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>high<span style="color: #339933;">;</span>
    <span style="color: #993333;">long</span> lstep <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span><span style="color: #009900;">&#41;</span> step<span style="color: #339933;">;</span>
&nbsp;
    type1 <span style="color: #339933;">=</span> is_numeric_string<span style="color: #009900;">&#40;</span>Z_STRVAL_P<span style="color: #009900;">&#40;</span>zlow<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> Z_STRLEN_P<span style="color: #009900;">&#40;</span>zlow<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    type2 <span style="color: #339933;">=</span> is_numeric_string<span style="color: #009900;">&#40;</span>Z_STRVAL_P<span style="color: #009900;">&#40;</span>zhigh<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> Z_STRLEN_P<span style="color: #009900;">&#40;</span>zhigh<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> NULL<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: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>type1 <span style="color: #339933;">==</span> IS_DOUBLE <span style="color: #339933;">||</span> type2 <span style="color: #339933;">==</span> IS_DOUBLE <span style="color: #339933;">||</span> is_step_double<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">goto</span> double_str<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>type1 <span style="color: #339933;">==</span> IS_LONG <span style="color: #339933;">||</span> type2 <span style="color: #339933;">==</span> IS_LONG<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">goto</span> long_str<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    convert_to_string<span style="color: #009900;">&#40;</span>zlow<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    转化为字符串，此函数的实现在zend_operators.c的536行：ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)</span>
    convert_to_string<span style="color: #009900;">&#40;</span>zhigh<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    low <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>Z_STRVAL_P<span style="color: #009900;">&#40;</span>zlow<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//    当所给字符串长度大于1时，取第一个字符</span>
    high <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>Z_STRVAL_P<span style="color: #009900;">&#40;</span>zhigh<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>low <span style="color: #339933;">&gt;</span> <span style="color: #339933;">*</span>high<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>lstep <span style="color: #339933;">&lt;=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        err <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> err<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">;</span> <span style="color: #339933;">*</span>low <span style="color: #339933;">&gt;=</span> <span style="color: #339933;">*</span>high<span style="color: #339933;">;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>low<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span>lstep<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        add_next_index_stringl<span style="color: #009900;">&#40;</span>return_value<span style="color: #339933;">,</span> low<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><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: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">signed</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span>low <span style="color: #339933;">-</span> lstep<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</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: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>high <span style="color: #339933;">&gt;</span> <span style="color: #339933;">*</span>low<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>lstep <span style="color: #339933;">&lt;=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        err <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">goto</span> err<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">;</span> <span style="color: #339933;">*</span>low <span style="color: #339933;">&lt;=</span> <span style="color: #339933;">*</span>high<span style="color: #339933;">;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>low<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span>lstep<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        add_next_index_stringl<span style="color: #009900;">&#40;</span>return_value<span style="color: #339933;">,</span> low<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><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: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">signed</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span>low <span style="color: #339933;">+</span> lstep<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">255</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    只支持ASCII的255个字符</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: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>    <span style="color: #666666; font-style: italic;">//    开始和结束相等，则只返回包含一个元素的数组</span>
        add_next_index_stringl<span style="color: #009900;">&#40;</span>return_value<span style="color: #339933;">,</span> low<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><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></pre></td></tr></table></div>

<p>对于浮点型和整形的处理基本类似，只有写入Hash Table的方法不同<br />
浮点型用的是add_next_index_double<br />
整形用的是add_next_index_long<br />
<br />
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-19-array_file-range/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_diff，array_udiff，array_diff_ukey，array_diff_uassoc，array_udiff_uassoc</title>
		<link>https://www.phppan.com/2010/03/php-source-17-array_diff-array_udiff-array_diff_ukey-array_diff_uassoc-array_udiff_uassoc-2/</link>
		<comments>https://www.phppan.com/2010/03/php-source-17-array_diff-array_udiff-array_diff_ukey-array_diff_uassoc-array_udiff_uassoc-2/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 00:56:59 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=588</guid>
		<description><![CDATA[PHP源码阅读笔记十七：array_diff，array_udiff，array_diff_ukey，arra [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记十七：array_diff，array_udiff，array_diff_ukey，array_diff_uassoc，array_udiff_uassoc<br />
这4个函数调用的是同一个函数php_array_diff，所不同的是他们的参数。<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
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">array_diff<span style="color: #339933;">:</span>        php_array_diff<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_NORMAL<span style="color: #339933;">,</span>
                                    DIFF_COMP_DATA_INTERNAL<span style="color: #339933;">,</span> DIFF_COMP_KEY_INTERNAL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
array_diff_ukey<span style="color: #339933;">:</span> php_array_diff<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_KEY<span style="color: #339933;">,</span>
                                 DIFF_COMP_DATA_INTERNAL<span style="color: #339933;">,</span> DIFF_COMP_KEY_USER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
array_udiff<span style="color: #339933;">:</span>    php_array_diff<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_NORMAL<span style="color: #339933;">,</span>
                            DIFF_COMP_DATA_USER<span style="color: #339933;">,</span> DIFF_COMP_KEY_INTERNAL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
f
array_diff_uassoc<span style="color: #339933;">:</span> php_array_diff<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_ASSOC<span style="color: #339933;">,</span>
                            DIFF_COMP_DATA_INTERNAL<span style="color: #339933;">,</span> DIFF_COMP_KEY_USER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
array_udiff_uassoc<span style="color: #339933;">:</span> php_array_diff<span style="color: #009900;">&#40;</span>INTERNAL_FUNCTION_PARAM_PASSTHRU<span style="color: #339933;">,</span> DIFF_ASSOC<span style="color: #339933;">,</span>
                            DIFF_COMP_DATA_USER<span style="color: #339933;">,</span> DIFF_COMP_KEY_USER<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>
程序说明：<br />
在获得了输入和作了相关错误处理后<br />
程序首先确认比较函数是哪个，此处，针对不同的behavior和data_compare_type有不同的比较函数，也有不同的输入参数错误处理<br />
然后对输入的参数复制并按照之前得到的diff_key_compare_func进行排序，排序调用的是zend_qsort函数<br />
然后初始化返回数组的hash table，并将第一个参数复制到返回数组<br />
最后遍历第一个参数的所有值，并判断是否不在其它参数中，<br />
在遍历过程中，如果某一个值在其它参数中则删除返回数组中所有等于这个值的元素，如果某一个值不在其它参数中，则跳过<br />
这样留下来的就是需要返回的值。</p>
<p>
EOF</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/03/php-source-17-array_diff-array_udiff-array_diff_ukey-array_diff_uassoc-array_udiff_uassoc-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源码阅读笔记四：count函数</title>
		<link>https://www.phppan.com/2010/01/php-sound-code-4-count/</link>
		<comments>https://www.phppan.com/2010/01/php-sound-code-4-count/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 03:22:14 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP数组]]></category>
		<category><![CDATA[PHP源码]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=500</guid>
		<description><![CDATA[PHP源码阅读笔记之count函数 在一些面试或考试中经常会看到count函数的身影，于是一探其究竟 对于非数 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>PHP源码阅读笔记之count函数<br />
<br />
在一些面试或考试中经常会看到count函数的身影，于是一探其究竟<br />
<br />
对于非数组的count处理<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
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">PHP_FUNCTION<span style="color: #009900;">&#40;</span>count<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    zval <span style="color: #339933;">*</span>array<span style="color: #339933;">;</span>
    <span style="color: #993333;">long</span> mode <span style="color: #339933;">=</span> COUNT_NORMAL<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>zend_parse_parameters <span style="color: #009900;">&#40;</span>ZEND_NUM_ARGS<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> TSRMLS_CC<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;z|l&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>array<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>mode<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> FAILURE<span style="color: #009900;">&#41;</span>
        <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span>Z_TYPE_P<span style="color: #009900;">&#40;</span>array<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">case</span> IS_NULL<span style="color: #339933;">:</span>    <span style="color: #666666; font-style: italic;">//    空值处理</span>
            RETURN_LONG<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">case</span> IS_ARRAY<span style="color: #339933;">:</span>    <span style="color: #666666; font-style: italic;">//    处理数组，包括其是递归</span>
            RETURN_LONG <span style="color: #009900;">&#40;</span>php_count_recursive <span style="color: #009900;">&#40;</span>array<span style="color: #339933;">,</span> mode TSRMLS_CC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">case</span> IS_OBJECT<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>    
    <span style="color: #339933;">#ifdef HAVE_SPL</span>
        <span style="color: #808080; font-style: italic;">/* it the object implements Countable we call its count() method */</span>
            zval <span style="color: #339933;">*</span>retval<span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_OBJ_HT_P<span style="color: #009900;">&#40;</span>array<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>get_class_entry <span style="color: #339933;">&amp;&amp;</span> instanceof_function<span style="color: #009900;">&#40;</span>Z_OBJCE_P<span style="color: #009900;">&#40;</span>array<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> spl_ce_Countable TSRMLS_CC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                zend_call_method_with_0_params<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>array<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;count&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>retval<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>retval<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    convert_to_long_ex<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>retval<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    RETVAL_LONG<span style="color: #009900;">&#40;</span>Z_LVAL_P<span style="color: #009900;">&#40;</span>retval<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    zval_ptr_dtor<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>retval<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
    <span style="color: #339933;">#endif</span>
        <span style="color: #808080; font-style: italic;">/* if not we return the number of properties (not taking visibility into account) */</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Z_OBJ_HT_P<span style="color: #009900;">&#40;</span>array<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>count_elements<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                RETVAL_LONG<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>SUCCESS <span style="color: #339933;">==</span> Z_OBJ_HT<span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>array<span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>count_elements<span style="color: #009900;">&#40;</span>array<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>Z_LVAL_P<span style="color: #009900;">&#40;</span>return_value<span style="color: #009900;">&#41;</span> TSRMLS_CC<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>    
              <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>    <span style="color: #666666; font-style: italic;">//    其它情况，如考试中常见的字符串等</span>
        RETURN_LONG<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</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></pre></td></tr></table></div>

<p>在手册中有说明：<br />
此函数对于对象，如果安装了 SPL，可以通过实现 Countable 接口来调用 count()。该接口只有一个方法 count()，此方法返回 count() 函数的返回值。<br />
<br />
对于数组长度的统计，如果mode使用默认值（0），则仅显示第一维数组的长度<br />
如下所示代码</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="php" style="font-family:monospace;"><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;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$arr2</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arr</span><span style="color: #339933;">,</span> <span style="color: #000088;">$arr</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arr2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$arr2</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">/*   输出结果：
2
8
*/</span></pre></td></tr></table></div>

<p>如果只是显示第一维数组，则直接返回保存数组的HashTable的nNumOfElements属性即可<br />
其实现的代码为：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//    php_count_recursive函数 array.c 251行</span>
cnt <span style="color: #339933;">=</span> zend_hash_num_elements<span style="color: #009900;">&#40;</span>Z_ARRVAL_P<span style="color: #009900;">&#40;</span>array<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
ZEND_API <span style="color: #993333;">int</span> zend_hash_num_elements<span style="color: #009900;">&#40;</span>HashTable <span style="color: #339933;">*</span>ht<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    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;">return</span> ht<span style="color: #339933;">-&gt;</span>nNumOfElements<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>如果想直接运行HashTable的一些简单操作，猛击<a href=" http://www.phppan.com/2009/12/php-hashtable-demo/"><strong>PHP源码中HashTable的简单示例</strong></a><br />
如果想查看了解数组存储或遍历的方式，猛击鸟哥的<a href="http://www.laruence.com/2009/08/23/1065.html">深入理解PHP之数组(遍历顺序)</a><br />
</p>
<p>如果启动了递归，即使用count($arr, 1)<br />
则程序会递归调用php_count_recursive函数<br />
针对HashTable，程序会遍历包含这一维数组的双向链表，然后再递归遍历每个节点存储的pData，真到遍历完所有的节点<br />
</p>
<p>【感受】<br />
HashTable很强大，如果要计算数组的长度还是调用count函数，重复发明轮子会是一种吃力不讨好的事情！</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2010/01/php-sound-code-4-count/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
