Меня путают с &
и &&
. У меня есть две книги 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 operation: & -> will do the bitwise AND operation , it just doing operation based on the bit values. && -> It will do logical AND operation. It is just the check the values is true or false. Based on the boolean value , it will evaluation the expression
Как говорят другие, один &
побитно. Он в основном преобразует левое значение в его представление битов, а правую сторону - в представление битов, а затем выполняет логическое И между ними и выводит результат.
Двойной &&
является либо истинным, либо ложным (на некоторых языках 0 или 1), если обе левая и правая стороны являются истинными (или ненулевыми).
Я бы также добавил, что это не только PHP. Это похоже на многие другие языки, такие как C, Java, Ruby и т.д.
Matthew answer о том, как логический оператор &&
- самая большая разница; логическое сравнение остановится, когда оно найдет что-то, что сломает цепочку. Кроме того, еще одна большая разница - это результат/значение результата.
Используя Logical And &&
, он всегда будет возвращать логический тип/значение, 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
для сравнения и не выполняет выполнение, если один операнд выходит из строя; Побитовое И использует 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;
Компилятор сгенерирует следующие коды операций сборки (результат W32Dasm для x86, я изменил адреса памяти с именами <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
в if (a && b)
мы видим, что если a == 0
, то он перескакивает и не проверяет остальное операнды.
Итак, я не согласен с комментарием animuson:
Они оба одинаковы, они просто используются для двух разных вещи для выполнения той же задачи. - animuson Мар 4 '10 в 1:42
Это не одно и то же, и оба они/должны использоваться для конкретных задач в зависимости от логики/потока программ.
&&
выполняется &
для операндов, сведенных к 1
или 0
.
(Другими словами, &&
является побитовым оператором под оговоркой, что он меняет свои операнды. То есть логические операции являются подмножеством побитовых операций.)