Побитовые операции

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

Поразрядное отрицание ~ (NOT)- устанавливает все не установленные биты и сбрасывает установленные

printf("%'06b", ~0b110110); // 001001

Побитовое И & (AND) — устанавливает бит в единицу только если он установлен в обоих операндах

printf("%'06b", 0b110101 & 0b011001); // 01000

Побитовое ИЛИ | (OR) — устанавливает бит если он установлен в одном из операндов или в обоих сразу

printf("%'06b", 0b110101 | 0b011001); // 111101

Побитовый XOR ^ — бит устанавливается, если он установлен в одном операнде и не установлен в другом операнде

printf("%'06b", 0b110101 ^ 0b011001); // 101100

Пример использования битовых масок

Эти операторы могут использоваться для манипулирования битовыми масками. Например:

file_put_contents("file.log", LOCK_EX | FILE_APPEND);

Здесь оператор | используется для объединения двух битовых масок. Хотя знак + имеет тот же эффект, | подчеркивает, что вы объединяете битовые маски, а не складываете два целых числа.

class Foo{
 const OPTION_A = 1;
 const OPTION_B = 2;
 const OPTION_C = 4;
 const OPTION_A = 8;
 private $options = self::OPTION_A | self::OPTION_C;
 public function toggleOption(int $option){
 $this->options ^= $option;
 }
 public function enable(int $option){
 $this->options |= $option; // Включить(активировать) $options независимо от его исходного состояния
 }
 public function disable(int $option){
 $this->options &= ~$option; // Выключить (отменить) $option независимо от его исходного состояния,
 // не затрагивая другие биты
 }
 /**Если включен хотя бы один из параметров */
 public function isOneEnabled(int $options) : bool{
 return $this->options & $option !== 0;
 // Используйте !== вместо >, потому что, если у $options активирован равен старший бит, 
 //это будет равноценно отрицательному целому числу
 }
 /** Если все опции включены */
 public function areAllEnabled(int $options) : bool{
 return ($this->options & $options) === $options;
 // обратите внимание на круглые скобки; учитывайте приоритет операторов
 }
}
  • оператор ^ для удобного переключения битовых масок.
  • оператор |, чтобы установить бит, игнорируя его исходное состояние или другие биты
  • оператор ~ для преобразования целого числа, в котором установлен только один бит, в целое число, в котором не указан только один бит
  • оператор & сбрасывает бит. Используя свойства &:
    • Поскольку &= с установленным битом ничего не будет делать ((1 & 1) === 1, (0 & 1) === 0), выполнение &= с целым числом
      если установлен только один бит, будет сброшен только этот бит, не влияющий на другие биты.
    • &= с неустановленным битом сбрасывает этот бит ((1 & 0) === 0, (0 & 0) === 0)
  • Использование оператора & с другой битовой маской отфильтрует все остальные биты, не установленные в этой битовой маске.
    • Если на выходе установлены какие-либо биты, это означает, что любая из опций включена.
    • Если на выходе есть все биты установленной битовой маски, это означает, что все опции в битовой маске включены

Имейте в виду, что операторы сравнения: (< > <= >= == === != !== <> <=>) имеют более высокий приоритет, чем битовая операторы: (| ^ &). Поскольку побитовые результаты часто сравниваются с помощью операторов сравнения, то можно запутаться.