msgbartop
PHP源码分析,Zend引擎分析,Web相关技术研究,Web技术分享–左手代码 右手诗
msgbarbottom

21 Feb 09 PHP字符串比较

我们在代码中用的最多的逻辑是什么?
你知道如下的几段代码的布尔结果分别是什么么?

var_dump("1" == "1e0");
var_dump("1" == "0x1");
var_dump("20" == "2e1");
var_dump("10" == "  0x0a");

等等;

对, 也许你会说在PHP手册的附录中有一部分关于这个问题的总结. 问题是,这只是知其然, 那么所以然是什么呢?

今天就有一个网友问了我一个问题:

	var_dump("1" == "1e0");  //true
	var_dump("1" == "1ef"); //false
    这两个的结果为什么不一样啊.

也就是说, 上面的等式a要成立, 那么唯一的解释就是PHP讲他们双发都当作int来比较.
但是, var_dump(“1e0″),或者var_dump(“1″),都是string啊.

那么, 到底PHP是怎么决定相比较的俩者的类型的呢?

还是老办法, 先从zend_language_scanner.l中找到==的opcode码 结果是T_IS_EQUAL
然后在zend_language_parse.y中找到编译器看到T_IS_EQUAL会做什么:

	 expr T_IS_EQUAL expr            { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }

那么接下就去zend_vm_def.h中寻找当ZE遇到ZEND_IS_EQUAL会做什么:

	ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
	{
		zend_op *opline = EX(opline);
		zend_free_op free_op1, free_op2;

		is_equal_function(&EX_T(opline->result.u.var).tmp_var,
			GET_OP1_ZVAL_PTR(BP_VAR_R),
			GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
		FREE_OP1();
		FREE_OP2();
		ZEND_VM_NEXT_OPCODE();
	}

看来,所有”==”判断都是由is_equal_function完成的, 让我们一起再看看它是什么样的:

	ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
	{
		if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
			return FAILURE;
		}
		convert_to_boolean(result);
		if (result->value.lval == 0) {
			result->value.lval = 1;
		} else {
			result->value.lval = 0;
		}
		return SUCCESS;
	}

哦, 看来不是, 还要进一步查看compare_function
代码太长, 不贴了. 在compare_function中, 当俩个比较操作数都是string的时候,会调用zendi_smart_strcmp:

    if (op1->type == IS_STRING && op2->type == IS_STRING) {
        zendi_smart_strcmp(result, op1, op2);
        COMPARE_RETURN_AND_FREE(SUCCESS);
    }

而在zendi_smart_strcmp中, 对于俩个字符串, 会首先判断他们是否是numeric_string, 如果是,那么就会转换成整形来比较..

那么什么是numeric string呢? 因为PHP不区分类型, 所以她采用一个策略, 当你的变量看起来是一个数字的时候, 那么她就认为这个变量是一个数字. 简单来说, numeric_string就是表示数字的字符串:

也就是说,如下的比较结果都是真:

	var_dump("1" == "1e0");
	var_dump("1" == "0x1");
	var_dump("20" == "2e1");
	var_dump("10" == "  0x0a");

呵呵, 读者们遇到过这个问题的困扰么?
ps: 谢谢bingxuefenggu网友的问题.

Related Posts:

  • No Related Post

Reader's Comments

  1. |

    终于发新文章了,还不错,但最近就这些进步吗?

  2. |

    @zvaly, 呵呵, 最近项目紧的很, 项目管理方面, 烦心事更多…

  3. |

    我还真是佩服你的思维,能在复杂的代码里随处逛,不会走丢,呵呵。最近在做什么有意思的东西吗?

  4. |

    @zvaly, 最近在基于Extjs做一个mis系统, 呵呵, 现在代码量已经7w了….

Leave a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word