我对 &
和 &&
搞混了。我有两本 PHP 书籍,一本说它们是一样的,但另一本说它们是不同的。我原本认为它们是一样的。
它们不是一样的吗?
我对 &
和 &&
搞混了。我有两本 PHP 书籍,一本说它们是一样的,但另一本说它们是不同的。我原本认为它们是一样的。
它们不是一样的吗?
$a = (false && foo());
foo
永远不会被调用,因为在求值为 false 后结果就已知了。另一方面,使用
$a = (false & foo());
foo
将被调用(另外,结果是0而不是false)。
Matthew's answer关于逻辑与运算符&&
是最大的区别;当逻辑比较找到破坏链的东西时,它将停止。另外一个重要的区别是结果类型/值。
使用逻辑与运算符&&
,它将始终返回布尔类型/值,即true
或false
。
false & 1 // int(0)
false && 1 // bool(false)
当返回具有逻辑结果的函数时,使用布尔类型/值非常重要,因为某些人可以使用“恒等比较运算符” ===
来比较结果(这很可能发生),如果您使用类似以下内容,则会失败:
(false & 1) === false // bool(false)
(true & true) === true // bool(false)
当您需要进行逻辑比较时,尤其是从具有逻辑结果的函数返回值时,请勿使用按位与&
。而是使用逻辑与&&
:
(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 '@'
当使用与整数和字符(这是一种特殊的整数)以外的类型时,要注意使用按位与&
。例如,如果您将其与实数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)
&&
使用 cmp <var>, 0
进行比较,如果一个操作数失败则不继续执行;位与Bitwise And 使用 and <var1>, <var2>
得出按位结果,然后测试其是否为0
值。我知道这个问题被标记为 php,而 php 的行为可能与 c 不同,但是我将使用一个小的 c 程序来演示编译器在使用逻辑与和位与时的行为。
假设我们有一个使用位运算和逻辑与的c程序:
int a = 0;
int b = 1;
int c = 2;
if (a & b)
c = 3;
if (a && b)
c = 4;
<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> // <--- <---
:0253
中,我们看到如果a == 0
,则在逻辑比较中跳过并且不检查其余操作数。因此,我不同意animuson's comment:
它们不是相同的东西,都应该根据程序的逻辑/流程用于特定任务。它们是相同的东西,只是用于完成相同任务的两个不同事物。 - animuson Mar 4 '10 at 1:42
AND运算:
& -> 执行按位与(bitwise AND)操作,它只是基于位值进行操作。 && -> 执行逻辑与(logical AND)操作。它只是检查值是真还是假。根据布尔值,它将评估表达式。
AND
对其操作数的布尔值执行短路(参见Matthew Flaschen的答案)and
操作,并计算出一个布尔值,而位运算 AND
对其操作数的每个单独位执行 and
操作。因此,0b0011 && 0b0110
计算结果为 TRUE
,但 0b0011 & 0b0110
计算结果为 0b0010
。 - Lux&
是按位的。它基本上将左侧值转换为其比特表示形式,右侧也转换为其比特表示形式,然后在它们之间执行逻辑AND并输出结果。&&
要么是真的,要么是假的(在某些语言中是0或1),如果左右两边都是真的(或非零)。&&
是对操作数进行&
运算后返回结果,操作数被归约为1
或0
。
换句话说,&&
是一个位运算符,但需要注意的是它会改变操作数。也就是说,逻辑操作是位操作的一个子集。