Ответ Мэтью о том, как Логический И &&
оператор является самой большой разницей; Логическое сравнение остановится, когда найдет что-то, что разорвет цепочку. Кроме того, есть еще одна большая разница - тип результата / значение .
Т.Л., др
Используя Logical And &&
, он всегда будет возвращать логический тип / значение , true
или false
.
false & 1 // int(0)
false && 1 // bool(false)
Важно использовать логический тип / значения при возврате функции с логическим результатом, потому что кто-то может использовать Идентичный оператор сравнения ===
для сравнения результатов (который высока вероятность того, что произойдет), и он потерпит неудачу, если вы используете что-то вроде этого:
(false & 1) === false // bool(false)
(true & true) === true // bool(false)
Никогда не используйте Побитовое И &
, когда вам нужно провести логическое сравнение, особенно при возврате значений из функций с логическими результатами. Вместо этого используйте Logical And &&
:
(false && 1) === false // bool(true)
(true && true) === true // bool(true)
При сравнении символов Logical And &&
всегда приводит к 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
, даже если оба операнда NOT 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>
для получения побитового результата и затем проверяет, имеет ли оно значение 0
. Я знаю, что этот вопрос помечен для php и php поведение может отличаться от c , но я буду использовать небольшую программу c чтобы продемонстрировать, как ведет себя компилятор при использовании Logical и Bitwise And .
Предположим, у нас есть программа в 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> // <--- <---
Компилятор не только использует различные инструкции для сравнения между Logical и Bitwaise And , но и в строке :0253
в if (a && b)
в логическом сравнении, мы видим, что если a == 0
затем он прыгает и не проверяет остальные операнды.
Итак, я не согласен с комментарием анимусона :
Они оба одно и то же, они просто используются для двух разных
вещи для выполнения той же задачи. - animuson 4 марта 2010 года в 1:42
Это не одно и то же, и оба / (должны быть) используются для конкретных задач в зависимости от логики / потока программ.