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/值truefalse

 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> // <--- <--- 

编译器不仅使用不同的指令来比较LogicalBitwaise ,而且在if (a && b)逻辑比较的行:0253中,我们看到如果a == 0那么它跳转并且不检查其余操作数。

所以,我不同意这个看法 :

他们都是一样的东西,他们只是用于完成相同任务的两个不同的东西。 – animuson 10年3月4日在1:42

它们不是一回事,根据程序的逻辑/stream程,它们都是/ (应该)被用于特定的任务。

&&在操作数减less到10

(换句话说, &&是一个按位运算符,它会改变它的操作数,也就是说,逻辑运算是按位运算的一个子集。