<?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; loose comparion</title>
	<atom:link href="https://www.phppan.com/tag/loose-comparion/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sun, 12 Apr 2026 03:47:23 +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的比较方式(loose and strict comparison)</title>
		<link>https://www.phppan.com/2011/07/php-loose-and-strict-comparison/</link>
		<comments>https://www.phppan.com/2011/07/php-loose-and-strict-comparison/#comments</comments>
		<pubDate>Mon, 25 Jul 2011 00:59:37 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[loose comparion]]></category>
		<category><![CDATA[PHP源码]]></category>
		<category><![CDATA[strict comparison]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1426</guid>
		<description><![CDATA[PHP的官方文档PHP type comparison tables 列出PHP类型和比较运算符在松散和严格比 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="text-indent: 2em;">PHP的官方文档<a style="color: #1299da; text-decoration: underline;" href="http://php.net/manual/en/types.comparisons.php">PHP type comparison tables</a> 列出PHP类型和比较运算符在松散和严格比较时的作用。当阅读这篇说明时， 其中有一个NOTE：<strong>HTML 表单并不传递整数、浮点数或者布尔值，它们只传递字符串。</strong> 道出了我们WEB开发过程中数据交互的本质。 一如XML，JSON等等都是字符串，只是依照不同的需求制定规则，让人们能够更好的理解。 再看HTTP协议，不管是request还是response，最终的载体都是字符串，只是依照不同的字段和规则实现所需要的缓存优化、信息传递等功能。 有点扯远了，回到今天的主题，PHP的比较方式。</p>
<p style="text-indent: 2em;">PHP的一些语言结构以及函数在默认实现上都是以松散比较的方式实现，如switch结构、array_keys、in_array、array_search等函数。 如果我们要使用严格的比较，对于switch语言结构本身并没有提供相关的实现，我们可以通过先将变量转换成对应的类型后再使用switch， 对于array_keys等函数，在PHP5以后都提供了$strict参数，将其设置为TRUE即可。 PHP的松散和严格比较表现最明显的是==和===。 我们从这两个语法结构来查看PHP对于松散和严格比较的实现。</p>
<p style="text-indent: 2em;">从词法分析开始，在Zend/zend_language_scanner.l文件中我们找到==和===对应的token，如下：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #e0882f;">&lt;</span>ST_IN_SCRIPTING<span style="color: #e0882f;">&gt;</span><span style="color: #99ff00;">"==="</span> <span style="color: #ffffff;">{</span>
    <span style="color: #ff8400;">return</span> T_IS_IDENTICAL<span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #e0882f;">&lt;</span>ST_IN_SCRIPTING<span style="color: #e0882f;">&gt;</span><span style="color: #99ff00;">"=="</span> <span style="color: #ffffff;">{</span>
    <span style="color: #ff8400;">return</span> T_IS_EQUAL<span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">PHP在词法结构上将这两种方式进行彻底的区分，==对应T_IS_EQUAL标识，===对应T_IS_IDENTICAL标识， 如果我们在写程序的过程中同时使用了以上两种符号会出现什么呢？如下代码：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #6d9cbe;">$num</span> <span style="color: #e0882f;">=</span> <span style="color: #1299da;">1</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$str</span> <span style="color: #e0882f;">=</span> <span style="color: #99ff00;">"1"</span><span style="color: #e0882f;">;</span>

<span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$num</span> <span style="color: #e0882f;">===</span> <span style="color: #6d9cbe;">$str</span> <span style="color: #e0882f;">==</span> <span style="color: #6d9cbe;">$num</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'phppan'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">这里就不给出答案了(^_^)。</p>
<p style="text-indent: 2em;">我们接着看语法解析，在Zend/zend_language_parse.y文件中我们可以看到如下代码：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #e0882f;">|</span>   expr T_IS_IDENTICAL expr        <span style="color: #ffffff;">{</span> zend_do_binary_op<span style="color: #ffffff;">(</span>ZEND_IS_IDENTICAL<span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>$$<span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>$<span style="color: #1299da;">1</span><span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>$<span style="color: #1299da;">3</span> TSRMLS_CC<span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span> <span style="color: #ffffff;">}</span>
<span style="color: #e0882f;">|</span>   expr T_IS_EQUAL expr            <span style="color: #ffffff;">{</span> zend_do_binary_op<span style="color: #ffffff;">(</span>ZEND_IS_EQUAL<span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>$$<span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>$<span style="color: #1299da;">1</span><span style="color: #e0882f;">,</span> <span style="color: #e0882f;">&amp;</span>$<span style="color: #1299da;">3</span> TSRMLS_CC<span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span> <span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">仅仅是通过上面的所给的代码，不去查看Zend/zend_complice.c中关于zend_do_binary_op函数的实现， 我们可以猜测出其最终会生成ZEND_IS_EQUAL和ZEND_IS_IDENTICAL中间代码。 最终所有的ZEND_IS_IDENTICAL中间代码对应的执行函数都会调用is_identical_function函数实现严格对比， 所有的ZEND_IS_EQUAL中间代码对应的执行函数都会调用compare_function函数实现松散对比。</p>
<p style="text-indent: 2em;">compare_function函数的具体实现在Zend/zend_operators.c文件。 compare_function的比较过程是一个穷举遍历比较的过程，程序在实现过程中对于传入的两个变量做类型的识别， 以两个变量的类型对为key，如字符串与字符串比较，数组和数组比较，浮点型和整型的比较，构造的类型对如果顺序不同，其对应的处理也是不同的。 如下列表，为所有可直接识别的类型对：</p>
<ul>
<li>整型和整型(LONG and LONG)</li>
<li>浮点型和整型(DOUBLE and LONG)</li>
<li>整型和浮点型(LONG and DOUBLE)</li>
<li>浮点型和浮点型(DOUBLE and DOUBLE)</li>
<li>数组和数组(ARRAY and ARRAY)</li>
<li>NULL和NULL</li>
<li>NULL和BOOL</li>
<li>BOOL和NULL</li>
<li>字符串和字符串(STRING and STRING)</li>
<li>NULL和字符串</li>
<li>字符串和NULL</li>
<li>对象和NULL</li>
<li>NULL和对象</li>
<li>对象和对象(OBJECT and OBJECT)</li>
</ul>
<p style="text-indent: 2em;">除此之外，还有一些特殊的情况，如下代码：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #6d9cbe;">$arr</span> <span style="color: #e0882f;">=</span> <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/array"><span style="color: #e2392d;">array</span></a><span style="color: #ffffff;">(</span><span style="color: #1299da;">1</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
<span style="color: #6d9cbe;">$num</span> <span style="color: #e0882f;">=</span> <span style="color: #1299da;">1</span><span style="color: #e0882f;">;</span>

<span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$arr</span> <span style="color: #e0882f;">==</span> <span style="color: #6d9cbe;">$num</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'yes'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span><span style="color: #ff8400;">else</span><span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #56db3a;">'no'</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">这些代码最终会输出no，但是在compare_function返回的结果为1。 他不属于上面所说的任一种类型对，由于第一个操作数为数组，则其走的程序流程分支为：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #ff8400;">else</span> <span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span>Z_TYPE_P<span style="color: #ffffff;">(</span>op1<span style="color: #ffffff;">)</span><span style="color: #e0882f;">==</span>IS_ARRAY<span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    ZVAL_LONG<span style="color: #ffffff;">(</span>result<span style="color: #e0882f;">,</span> <span style="color: #1299da;">1</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span>
    <span style="color: #ff8400;">return</span> SUCCESS<span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span></pre>
<p style="text-indent: 2em;">以上的代码将1赋值给result，但是在中间代码的执行函数中，执行完compare_function后会执行如下代码：</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;">ZVAL_BOOL<span style="color: #ffffff;">(</span>result<span style="color: #e0882f;">,</span> <span style="color: #ffffff;">(</span>Z_LVAL_P<span style="color: #ffffff;">(</span>result<span style="color: #ffffff;">)</span> <span style="color: #e0882f;">==</span> <span style="color: #1299da;">0</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span><span style="color: #e0882f;">;</span></pre>
<p style="text-indent: 2em;">因为比较的最终结果为真假，而在比较中除了0，其他的都是不等于。</p>
<p style="text-indent: 2em;">如果是比较字符串和整数，则其最终都将字符串转化成数字（整数或浮点数）再进行比较，即最终比较的方法是可以识别的类型对之一。 如果是数组和数组的比较，由于存在数组与数组的对比，则其直接调用zend_compare_arrays完成比较。</p>
<p style="text-indent: 2em;">与松散比较类似，严格比较也有一个对应的函数&#8211;is_identical_function。 同样，其实现也在Zend/zend_operator.c文件。 和loose comparison不同，strict comparison在严格意义上来说进行的不是一个纯粹的比较过程，它首先会判断两个变量所处的ZVAL容器的类型是否一样， 如果不一样直接返回0，即不相等。 如果两个ZVAL窗口的类型一样，则根据比较的第一个操作数的类型作区分，然后判断两个操作数的值是否一样， 这里之所以要分别对待每种类型，是因为在PHP中不同类型的值存储的位置不同，其对应的获取方法也不相同。</p>
<p style="text-indent: 2em;">在看完了PHP关于松散比较和严格比较的源码，我们最后看一段代码，你觉得应该会输出什么？</p>
<pre style="background-color: #333333; color: #ffffff; font: normal normal normal 13px/normal 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Courier New', monospace; overflow-x: auto; overflow-y: auto; padding: 10px;"><span style="color: #6d9cbe;">$str</span> <span style="color: #e0882f;">=</span> <span style="color: #99ff00;">"0"</span><span style="color: #e0882f;">;</span>
<span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><a style="color: #1299da; text-decoration: none;" href="http://www.php.net/empty"><span style="color: #e2392d;">empty</span></a><span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$str</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #1299da;">1</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span>

<span style="color: #6d9cbe;">$str</span> <span style="color: #e0882f;">=</span> <span style="color: #99ff00;">"00"</span><span style="color: #e0882f;">;</span>
<span style="color: #ff8400;">if</span> <span style="color: #ffffff;">(</span><a style="color: #1299da; text-decoration: none;" href="http://www.php.net/empty"><span style="color: #e2392d;">empty</span></a><span style="color: #ffffff;">(</span><span style="color: #6d9cbe;">$str</span><span style="color: #ffffff;">)</span><span style="color: #ffffff;">)</span> <span style="color: #ffffff;">{</span>
    <a style="color: #1299da; text-decoration: none;" href="http://www.php.net/echo"><span style="color: #e2392d;">echo</span></a> <span style="color: #1299da;">2</span><span style="color: #e0882f;">;</span>
<span style="color: #ffffff;">}</span></pre>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/07/php-loose-and-strict-comparison/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
