Побитовые операции над логическими значениями


Насколько мне известно, побитовые операторы выполняют проверку всех соответствующих битов, как в:

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

Итак, из этого у меня есть два вопроса:

  1. Какой смысл в && и ||, если мы (как кажется) можем вместо этого использовать & и | для логических значений?
  2. Почему я не могу сделать ~true (или другими словами, почему не поддерживаются логические значения)? Для меня звучит логично, что ~true возвращает false.

Я придумал одну вещь, заключающуюся в том, что && и || будут (иногда) приводить значения в bool, а затем возвращать правильные результаты, если мы (по ошибке) случайно передадим значение, которое не относится к типу bool. Но чтобы решить эту проблему, не можем ли мы сначала просто сделать слепок? Например:

if ((bool)$foo & (bool)$bar) { ...

Такое чувство, что я упускаю здесь важную деталь, которая все меняет... Но на всякий случай, если я этого не сделал, я включил как можно больше информации. Может ли кто-нибудь помочь мне понять это немного лучше, ответив на мои два вопроса? Я довольно смущен в этот момент, и я думал об этом довольно долго.

Author: Max, 2014-09-16

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)

Резюме

Использовать побитовое операторы только в том случае, если вам нужно изменить биты.

 3
Author: R1tschY, 2014-09-17 07:45:31

true и false логические флаги, хотя и хранятся в памяти в виде 32-разрядных или 64-разрядных значений, следует рассматривать просто как логические значения с двумя состояниями. В конечном итоге вы будете использовать его только на охранниках плечевого пояса, поэтому вам не следует делать над ними арифметические вычисления. && и || вычисляются как логические флаги, побитовые операторы & и |вычисляются как одни и те же операнды (например, int & int вычисляется как int, int && int вычисляется как логическое значение).

История такова: используйте && и ||, когда вам нужно принимать решения на некоторых условиях. Используйте & и | для выполнения логической арифметики над значениями.

Это C++

C не имеет встроенных логических значений, поэтому любое ненулевое значение равно true, а ноль равен false.

 0
Author: Gianluca Ghettini, 2014-09-17 08:16:36