奇怪的行为:(0=“string”)为真| switch(0){}给出第一种情况';case”;a”:';


strange behavior: ( 0 == "string") is true| switch(0){} gives the first case 'case "a": '

这是怎么发生的?

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

太长;未阅读

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

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


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


世界会结束吗,PHP解释器是在骗我吗

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

当比较不同类型的对象时,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((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";

它被称为"类型杂耍",是一种语言特性(据我所知,每种松散类型的语言)。比较运算符需要两个相同类型的值。如果不存在相同的类型,PHP会尝试将两者强制转换为最常见的类型,即这里的int。这意味着

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