5

怎么可能发生?

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
4

2 回答 2

7

太长; 没读过

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

包括这两者的例子可以在这篇文章的后面找到。


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


世界末日会不会是PHP解释器在骗我?

并非如此,尽管乍一看这可能出乎意料,但它实际上是该语言的一个功能(类型杂耍),并且在其他情况下通常非常有用。

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

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

以下行等同于您在问题中的内容:

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

嗯,等等.. erhm,什么!?

由于从“字符串”到数值的转换实际上是不可能的,因此隐式转换将产生0(由语言指定)。

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

这主要是因为这种方式的隐式转换将有助于进行数学运算。

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

我们知道compare 0to0应该 compare 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 起有更严格的比较运算符;===.

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

只有当它们是同一类型时,它才会真正比较两者,下面的函数在很多方面相当于 using ===

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";
于 2012-07-13T09:56:42.473 回答
5

它被称为“类型杂耍”,它是一种语言功能(据我所知,每种松散类型的语言)。比较运算符需要两个相同类型的值。如果没有相同的类型,PHP 会尝试将两者都转换为最常见的类型,即int此处。这表示

0=="some string"
0==0
true
于 2012-07-13T09:43:34.360 回答