奇怪的行为:(0 ==“string”)是真的switch(0){}给出第一个案例'case“a”:'

时间:2012-07-13 09:40:22

标签: php

this怎么可能发生?

var_dump(0=="some string"); // yields true, why?

switch(0) {
  case "a":
    echo "a"; // <-- we get here, why?
    break;  

  case "b":
    echo "b";
    break;   

  default:
    echo "def";
    break;
} 

根据这个

0=="some string"
0==(int)"some string"
0==0
true

这也是合乎逻辑的:

        0=="some string"
(string)0=="some string"
      "0"=="some string"
       false

2 个答案:

答案 0 :(得分:7)

太长;没看过

在这个相当长的帖子中总结一下;如果您不希望发生这种情况,则会发生从一种类型到另一种类型的隐式转换,请使用更严格的===或显式转换。

这两个例子可以在这篇文章中找到。


关于类型杂耍的进一步阅读可以在手册的相关部分找到,位于here


世界将会结束,PHP解释器是骗我的吗?

不是真的,即使初看起来这可能是意想不到的,它实际上是该语言的一个特征( type-juggling ),并且在其他情况下它通常非常有用。

当比较不同类型的对象时,PHP解释器需要找到一个共同点,如果它们是不同类型的,那么它自然会隐式地尝试将一个转换为另一个。

在这种情况下,它会尝试将字符串“string”转换为数字值。

以下行与您的问题相同:

if (0 == intval ("string"))

<嗯>嗯,等等......嗯,什么!?

由于实际上不可能从“string”转换为数值,因此隐式转换将产生0(由语言指定)。

  

这是将转换为int的字符串,因为这就是PHP   委员会决定。

     

这主要是因为这种方式的隐式转换在进行数学运算时会有所帮助。

     

与其他方式相比,期待这种行为更为常见   周围。

我们知道将00进行比较应该比较true,这正是发生的事情。以下内容相当于您在问题中所拥有的内容,尽管进一步解释事情更为冗长。

function equal_ ($lhs, $rhs) {
  if (gettype ($lhs) == 'integer')
    $rhs = intval($rhs);

  /* ... */

  return $lhs === $rhs;
}

if (equal_ (0, "string")) {

}

但是嘿..嘿,坚持下去!

“当我使用我的开关时,我甚至没有调用任何比较运算符,该示例会发生什么?”

你没有,但解释器的内部将在执行你的 switch-statement 时。

要解决此问题,您需要显式转换要搜索的针,或者用作标签的值,以便它们具有相同的类型。

您之前的代码段可以编写如下,以便进行更严格的比较。

switch((string)0) {
  case "a":
    echo "a";
    break;  

  case "b":
    echo "b";
    break;   

  default:
    echo "def";
    break;
} 

如果我不想使用此“功能”该怎么办?

自PHP4起,有一个更严格的比较运算符; ===

这将不允许对其中一个操作数进行隐式转换,而是首先检查操作数是否属于同一类型 - 如果不是;它将返回false。

只有当它们属于同一类型才真正比较两者时,下面的函数在很多方面等同于使用===

function strict_equal_ ($lhs, $rhs) {
  if (gettype ($lhs) != gettype ($rhs))
    return false;

  return $lhs == $rhs;
}

if (strict_equal_ (0, "string"))
  echo "True";
else
  echo "False";

答案 1 :(得分:5)

它被称为"type juggling",它是一种语言功能(据我所知,每种松散类型的语言)。比较运算符需要两个相同类型的值。如果没有相同类型的PHP,则尝试将两者都强制转换为最常见的类型,即int。这意味着

0=="some string"
0==0
true