Побитовые операции над логическими значениями
Насколько мне известно, побитовые операторы выполняют проверку всех соответствующих битов, как в:
echo 64 | 32; //prints 96
echo 'a' & 'b'; //prints `
В то время как условные операторы &&
и ||
выполняют операции над логическими значениями:
echo (int)(true && false); //prints: 0
echo (int)(true || false); //prints: 1
Когда я (мысленно) хочу предсказать результат побитовой операции, я сначала преобразую значения в их двоичное представление (которое зависит от типа данных). После этого я сравниваю его бит за бит и преобразую результат в подходящий тип вывода (который, я полагаю, определяется операндами). Хотя в какой-то момент я попытался сделать то же самое с логическими значениями, которые (насколько мне известно) состоят только из одного бита в памяти, делая true
соответствующим 1₂
и делая false
соответствующим 0₂
(в двоичном формате). Поэтому выполнение побитовых операций с этими значениями должно привести к аналогичному результату, как с &&
и ||
, верно? Чтобы показать вам, что я имею в виду:
true & false => 1₂ & 0₂ => 0₂ => false
true | false => 1₂ | 0₂ => 1₂ => true
~true => ~1₂ => 0₂ => false
(Не включая xor
, так как нет соответствующего условного логического оператор.)
Мне кажется, что поведение должно быть действительно эквивалентно условным операторам:
true && false => false
true || false => true
!true => false
Поэтому я установил этот код, чтобы проверить его:
echo "true AND false: " . ((true && false) ? "1" : "0") . "<br />\n";
echo "true OR false: " . ((true || false) ? "1" : "0") . "<br />\n";
echo "NOT true: " . ((!true) ? "1" : "0") . "<br />\n";
echo "<br />\n";
echo "true BITAND false: " . ((true & false) ? "1" : "0") . "<br />\n";
echo "true BITOR false: " . ((true | false) ? "1" : "0") . "<br />\n";
echo "BITNOT true: " . ((~true) ? "1" : "0") . "<br />\n";
Это дало мне следующий результат:
Истинно И ложно: 0
правда ИЛИ ложь: 1
НЕВЕРНО: 0Истинный БИТ И ложь: 0
истинный БИТОР ложь: 1Неустранимая ошибка: Неподдерживаемые типы операндов в C:\Abyss Паутина Server\htdocs\handler.php в режиме онлайн 21
Итак, из этого у меня есть два вопроса:
- Какой смысл в
&&
и||
, если мы (как кажется) можем вместо этого использовать&
и|
для логических значений? - Почему я не могу сделать
~true
(или другими словами, почему не поддерживаются логические значения)? Для меня звучит логично, что~true
возвращаетfalse
.
Я придумал одну вещь, заключающуюся в том, что &&
и ||
будут (иногда) приводить значения в bool
, а затем возвращать правильные результаты, если мы (по ошибке) случайно передадим значение, которое не относится к типу bool
. Но чтобы решить эту проблему, не можем ли мы сначала просто сделать слепок? Например:
if ((bool)$foo & (bool)$bar) { ...
Такое чувство, что я упускаю здесь важную деталь, которая все меняет... Но на всякий случай, если я этого не сделал, я включил как можно больше информации. Может ли кто-нибудь помочь мне понять это немного лучше, ответив на мои два вопроса? Я довольно смущен в этот момент, и я думал об этом довольно долго.
2 answers
Ответ 1
Части логических выражений (||
, &&
, !
, ...) оцениваются только при необходимости (слева направо):
if ($a | func()) { } // func is always called
if ($a || func()) { } // func is not called if $a is true,
// because expression is true whatever func will return
if ($a && func()) { } // func is not called if $a is false,
// because expression is false whatever func will return
func() || exit(); // exit() will be called if func() returns false
Взгляните на документацию: http://php.net/manual/en/language.operators.logical.php
Ответ 2
~true
кажется, не имеет смысла: true
является 0x00...01
и ~true
будет 0xff...fe
и не false
0x000...0
:
var_dump(~((int)true)); // prints: int(-2)
echo dechex(~((int)true)); // prints: fffffffffffffffe
Вместо этого используйте !
-оператор:
var_dump(!true); // prints: bool(false)
Резюме
Использовать побитовое операторы только в том случае, если вам нужно изменить биты.
true
и false
логические флаги, хотя и хранятся в памяти в виде 32-разрядных или 64-разрядных значений, следует рассматривать просто как логические значения с двумя состояниями. В конечном итоге вы будете использовать его только на охранниках плечевого пояса, поэтому вам не следует делать над ними арифметические вычисления. &&
и ||
вычисляются как логические флаги, побитовые операторы & и |вычисляются как одни и те же операнды (например, int & int
вычисляется как int
, int && int
вычисляется как логическое значение).
История такова:
используйте &&
и ||
, когда вам нужно принимать решения на некоторых условиях. Используйте &
и |
для выполнения логической арифметики над значениями.
Это C++
C не имеет встроенных логических значений, поэтому любое ненулевое значение равно true
, а ноль равен false
.