问题抛出:
var_dump("1" == "1e0"); //true
var_dump("1" == "1ef"); //false
这两个的结果为什么不一样啊.
这确实是一个很郁闷的问题,为什么呢?
问题的分析:
当然一点点看源码。看相关的引用到函数。
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
简单粗暴解决问题:
1,==时候php最终会用到C的strcmp函数
查看compare_function
在compare_function中, 当俩个比较操作数都是string的时候,会调用zendi_smart_strcmp(具体就不贴代码了)。
在compare_function中, 当俩个比较操作数都是string的时候,会调用zendi_smart_strcmp(具体就不贴代码了)。
但是如果是strcmp的话,那么答案的结果应该是这样的:
var_dump("1" == "1e0"); //false
var_dump("1" == "1ef"); //false
这两个的结果为什么不一样啊.
起码他们一样了!!!哈哈。但是php中确实都是一个true一个false。妈蛋!!!
2,难道==前,==两边发了什么
沃日,不会吧!当一切可能都不可能的话,那么不可能就变成了可能。
还是在
zendi_smart_strcmp中,看来不把他贴出来难平猿愤了!源码如下:
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
{
int ret1, ret2;
long lval1, lval2;
double dval1, dval2;
if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
(ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
if (ret1!=IS_DOUBLE) {
dval1 = (double) lval1;
} else if (ret2!=IS_DOUBLE) {
dval2 = (double) lval2;
} else if (dval1 == dval2 && !zend_finite(dval1)) {
/* Both values overflowed and have the same sign,
* so a numeric comparison would be inaccurate */
goto string_cmp;
}
Z_DVAL_P(result) = dval1 - dval2;
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
} else { /* they both have to be long's */
ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
}
} else {
string_cmp:
Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
}
}
果然, 对于俩个字符串, 会首先判断他们是否是numeric_string, 如果是,那么就会转换成整形来比较.关于转换就要细看C的strtol函数了!那么什么是numeric string呢? 因为PHP不区分类型, 所以她采用一个策略, 当你的变量看起来是一个数字的时候, 那么她就认为这个变量是一个数字. 简单来说, numeric_string就是表示数字的字符串.太坑了吧!所以大家还是用=== 吧!!!
3,再看问题
var_dump("1" == "1e0"):1,numeric_string策略通过;2,strcmp("1",strtol("1e0"))。
var_dump("1" == "1ef"):1,numeric_string策略不通过;2,strcmp("1","1ef")。
所以还是多用===!!!!