Php比较优先混淆

时间:2013-09-02 12:20:16

标签: php operator-precedence comparison-operators

我在查看我的实习生代码,我偶然发现了这样的事情:

//k* are defined constants
if ($a == 0 & $b >= k0) $a = 1;
if ($a == 1 & $b >= k1) $a = 2;
if ($a == 2 & $b >= k2) $a = 3;

我认为他犯了一个错误,混淆&&&(我除了逻辑AND)

但事实上,他的代码按预期工作,我无法理解为什么。在我看来,>=优先于==,它也优先于&reference)。

所以,我测试了(1 == 0 & 1 >= 0)并输出了0。我期待1,因为在我看来,它就像是:

  • 1 >= 0返回true
  • 然后1 == 0提供false
  • 所以表达式现在是(false & true),我认为这等于(0 & 1)
  • 等于1 ...
  • 所以他的&就像||

我错在哪里?

4 个答案:

答案 0 :(得分:3)

在PHP中,两个布尔值上的按位AND &将它们转换为整数(即​​一个或零)并执行AND。当此操作的结果被评估为布尔值时,结果实际上等同于逻辑AND &&的相同功能。

0 & 1 // 0, false
1 & 0 // 0, false
1 & 1 // 1, true
0 & 0 // 0, false

Proof

实习生会误解这两个操作员,因为没有充分的理由这样做 - 你会失去短路评估并添加一些不必要的类型转换。

但在这种情况下,它确实以与逻辑AND相同的方式工作。

理论上,您的优先级参数是正确的,但只有在存在歧义时才适用:

$foo = $b >= k1;
if ($a == 1 & $foo) $a = 2;

这可能会产生与您想要的结果不同的结果,您应该写:

$foo = $b >= k1;
if (($a == 1) & $foo) $a = 2;
// or
if ($a == (1 & $foo)) $a = 2;

......取决于你想要的东西。

但是既然你做不到:

$foo = 0 & $b;
if ($a == $foo >= k1) $a = 2;

...代码展示只能以一种方式解释,因此它是“安全的”,即使它不是你想要的。

然而,除非你开始混合逻辑和按位运算符,否则仍然存在很小的危险 - 优先级方面,两种类型的运算符紧挨着彼此,所以类似于:

if ($foo & $bar && $baz | $qux) // ...

......面临意外事件的严重危险。

值得注意的是,&实际上是相当可靠的(它仍然会给出预期的结果,它只是效率低下而且不会短路) - 它可能会开始变为奇数|的东西。

然而,你显然永远不会这样做,你会使用大括号,因为这个版本的可读性非常不透明。

答案 1 :(得分:1)

你的错误在这里:

  • 所以表达式现在是(false& true),我认为它等于(0& 1)
  • 等于1 ...

0 & 1实际上等于0

布尔代数与按位运算符同构,这是二进制计算机的基础。

答案 2 :(得分:1)

(0 & 1)0

&运算符对于逻辑值true和false的作用与&&相同,除了它没有短路,即在可能的情况下省略对第二个表达式的评估。

答案 3 :(得分:1)

这很简单。如您所知,按位&返回两个操作数中“on”的位:

0011
0010
----- &
0010

按位|将设置在一个(或两个)操作数中设置的所有位:

0011
0010
----- |
0011

在您的情况下,truefalse被强制为整数(0和1),这会产生

0001
0000
----- &
0000

就是这么简单