我在查看我的实习生代码,我偶然发现了这样的事情:
//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
... &
就像||
。我错在哪里?
答案 0 :(得分:3)
在PHP中,两个布尔值上的按位AND &
将它们转换为整数(即一个或零)并执行AND。当此操作的结果被评估为布尔值时,结果实际上等同于逻辑AND &&
的相同功能。
0 & 1 // 0, false
1 & 0 // 0, false
1 & 1 // 1, true
0 & 0 // 0, false
实习生会误解这两个操作员,因为没有充分的理由这样做 - 你会失去短路评估并添加一些不必要的类型转换。
但在这种情况下,它确实以与逻辑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)
你的错误在这里:
0 & 1
实际上等于0
。
布尔代数与按位运算符同构,这是二进制计算机的基础。
答案 2 :(得分:1)
(0 & 1)
是0
&运算符对于逻辑值true和false的作用与&&相同,除了它没有短路,即在可能的情况下省略对第二个表达式的评估。
答案 3 :(得分:1)
这很简单。如您所知,按位&
返回两个操作数中“on”的位:
0011
0010
----- &
0010
按位|
将设置在一个(或两个)操作数中设置的所有位:
0011
0010
----- |
0011
在您的情况下,true
和false
被强制为整数(0和1),这会产生
0001
0000
----- &
0000
就是这么简单