PHP中&和&&的区别
我对&
和&&
感到困惑。 我有两本PHP书。 一个说他们是一样的,但另一个说他们是不同的。 我以为他们也一样。
他们不一样吗?
&
是按位与。 请参阅按位运算符 。 假设你做14 & 7
:
14 = 1110 7 = 0111 --------- 14 & 7 = 0110 = 6
&&
是合乎逻辑的。 请参阅逻辑运算符 。 考虑这个真值表:
$a $b $a && $b false false false false true false true false false true true true
其他答案是正确的,但不完整。 逻辑“与”的一个关键特征是它短路,意味着第二个操作数只在必要时进行评估。 PHP手册给出了下面的例子来说明:
$a = (false && foo());
foo
永远不会被调用,因为结果在评估false后是已知的。 另一方面与
$a = (false & foo());
foo
将被调用(也是,结果是0而不是false)。
AND操作: & - >将执行按位AND操作,它只是基于的操作 位值。 && - >它会做逻辑与操作。 这只是检查值是 对或错。 基于布尔值,它将评估 expression
正如其他人所说,一个单一的&
是明智的。 它基本上将左边的值转换成比特表示,右边的转换成比特表示,然后在它们之间执行逻辑与并输出结果。
如果左侧和右侧均为真(或非零),则Double &&
为真或假(在某些语言中为0或1)。
我还补充说,这不仅仅是在PHP中。 就像C,Java, Ruby等许多其他语言一样。
TL; DR
马修关于逻辑和运算符是如何最大的区别的答案 ; 逻辑比较将会停止,当它会发现一些打破链条。 另外,还有一个更大的区别就是结果types/值 。
通过使用Logical And &&
,它将始终返回一个布尔types/值 , true
或false
。
false & 1 // int(0) false && 1 // bool(false)
返回具有逻辑结果的函数时,使用布尔types/值是很重要的,因为有人可以使用Identical比较运算符 ===
比较结果(这很可能发生),如果使用类似的结果这个:
(false & 1) === false // bool(false) (true & true) === true // bool(false)
切勿使用按位和 &
当您需要进行逻辑比较时,尤其是从函数返回具有逻辑结果的值时。 而是使用Logical And &&
:
(false && 1) === false // bool(true) (true && true) === true // bool(true)
比较字符时, 逻辑和 &&
将总是结果为true
,即使有NUL
字符,除非它被转换为整数:
'A' && 'B' // bool(true) 'A' && 0 // bool(false) 'A' && '\0' // bool(true) 'A' && (int)'\0' // bool(false)
如果使用“ 按位”和 &
与”字符,将导致与这两个字符之间的“ 按位和”操作对应的字符:
'A' & 'B' // string(1) "@" 01000001 // ASCII 'A' & 01000010 // ASCII 'B' = 01000000 // ASCII '@'
请注意Bitwise的用法以及 &
与整数和字符 (这是特殊types的整数)以外的types一起使用时。 例如,如果将它与实数float / double一起使用 ,则即使两个操作数都不为0
,结果也可能为0
:
1.0 & 1.0 // int(1) 2.0 & 1.0 // int(0) 1.0 && 1.0 // bool(true) 2.0 && 1.0 // bool(true)
另外,如果我们进入汇编指令级别,我们可以看到这种差异以及编译器如何处理, Logical And &&
使用cmp <var>, 0
进行比较,如果一个操作数失败,则不会继续执行; 按位和使用and <var1>, <var2>
做一个按位结果,然后testing它是否为0
值。 我知道这个问题是标记为PHP和PHP的行为可能不同于C ,但我会用一个小型的C程序来演示如何使用逻辑和按位和编译器的行为。
让我们假设我们有一个使用按位和逻辑的程序, 并且 :
int a = 0; int b = 1; int c = 2; if (a & b) c = 3; if (a && b) c = 4;
编译器将生成下面的程序集操作码( x86的W32Dasm结果 ;为了简单起见,我使用<variable>
名称更改了内存地址):
:0229 mov <a>, 0 :0230 mov <b>, 1 :0237 mov <c>, 2 // if (a & b) begins :023E mov eax, <a> :0241 and eax, <b> // a bitwise and b, result stored to eax :0244 test eax, eax // test eax and set ZeroFlag if equals to 0 :0246 je 024F // >--- Jump if ZeroFlag is set :0248 mov <c>, 3 // | or set c = 3 // if (a && b) begins | :024F cmp <a>, 0 // <--- compare a to 0 and sets ZeroFlag if difference is 0 :0253 je 0262 // >--- Jump if ZeroFlag is set (a == 0) :0255 cmp <b>, 0 // | compare b to 0 and sets ZeroFlag if differemce is 0 :0259 je 0262 // | >--- Jump if ZeroFlag is set (b == 0) :025B mov <c>, 4 // | | or set c = 4 :0262 <program continues> // <--- <---
编译器不仅使用不同的指令来比较Logical和Bitwaise ,而且在if (a && b)
逻辑比较的行:0253
中,我们看到如果a == 0
那么它跳转并且不检查其余操作数。
所以,我不同意这个看法 :
他们都是一样的东西,他们只是用于完成相同任务的两个不同的东西。 – animuson 10年3月4日在1:42
它们不是一回事,根据程序的逻辑/stream程,它们都是/ (应该)被用于特定的任务。
&&
在操作数减less到1
或0
。
(换句话说, &&
是一个按位运算符,它会改变它的操作数,也就是说,逻辑运算是按位运算的一个子集。