Битовые операции проще всего понять не через десятичные числа, а через восьмеричную запись прав доступа Unix: команда chmod 640 — это не просто три цифры, а три отдельные тройки битов «чтение-запись-выполнение», собранные в одно число операцией OR. Именно поэтому побитовую логику почти никогда не показывают в десятичной системе — она легко читается только в двоичном или шестнадцатеричном виде.
AND, OR, XOR, NOT — четыре базовые операции
- AND (&) — результирующий бит равен 1, только если оба входных бита равны 1. В
chmodименно AND с маской проверяет, установлен ли конкретный флаг доступа. - OR (|) — результирующий бит равен 1, если хотя бы один из входных битов равен 1. Так три отдельных права (r=4, w=2, x=1) складываются в одну цифру, например 4|2|1 = 7.
- XOR (^) — результирующий бит равен 1, если входные биты различны; применение XOR дважды с тем же значением возвращает оригинал.
- NOT (~) — инвертирует каждый бит числа.
Чем побитовый AND отличается от логического
Логический AND (&& в большинстве языков) работает с булевыми значениями целиком и даёт true/false, тогда как побитовый AND (&) обрабатывает каждый бит двух чисел отдельно и возвращает число. Путаница между ними — распространённая причина багов.
Почему битовые маски удобнее хранить в двоичном или шестнадцатеричном виде
Число прав доступа 6 в десятичной системе ничего не говорит о том, какие именно флаги установлены, а вот 0b110 сразу читается как «чтение и запись, без выполнения». Ровно поэтому конвертер систем счисления и инструмент побитовых операций используются в связке: прежде чем применять AND/OR/XOR, число почти всегда переводят в двоичный или шестнадцатеричный вид, где структура битов видна напрямую.
Зачем это нужно
- Эффективно хранить и проверять набор булевых флагов в одном числе.
- Понимать низкоуровневый код работы с сетевыми протоколами или бинарными форматами.
- Оптимизировать вычисления там, где побитовые операции быстрее обычной арифметики.
Ловушка с приоритетом операторов
В большинстве языков программирования побитовые операторы & и | имеют более низкий приоритет, чем операторы сравнения — поэтому выражение вроде if (a & b == c) на самом деле вычисляется как a & (b == c), а не так, как ожидает автор. Это одна из самых распространённых причин трудноуловимых багов при работе с битовыми масками, и надёжный способ избежать её — всегда явно расставлять скобки вокруг побитовых операций.