Главная chevron_right Структура chevron_right Побитовые операторы chevron_right ~ (bitwise NOT)

~ (bitwise NOT)

Оператор ~ инвертирует все биты числа: каждый 0 становится 1 и наоборот — удобно для сброса битов через маски вида ~(1 << N).

Полная статья

Описание

Побитовый оператор NOT обозначается символом тильды ~ и является унарным — он применяется к одному операнду, стоящему справа от него. В отличие от & и |, которым нужны два операнда, ~ просто переворачивает все биты числа: каждый 0 превращается в 1, а каждый 1 — в 0.

Другими словами:

0  1    operand1
-----
1  0   ~operand1

Пример кода

    int a = 103;  // двоичное: 0000000001100111
    int b = ~a;   // двоичное: 1111111110011000 = -104

Как читать результат

Если применить ~ к числу типа int и получить неожиданно отрицательный результат — например, ~103 даст -104 — это не ошибка. Всё дело в том, как целые числа со знаком хранятся в памяти.

В типе int старший бит является знаковым: если он равен 1, число считается отрицательным. Такой способ представления называется дополнением до двух (Twos_complement). После инверсии всех битов знаковый бит тоже меняется, и положительное число превращается в отрицательное.

Полезное правило: для любого целого числа x выражение ~x всегда равно -x - 1. Это прямое следствие дополнения до двух и помогает быстро проверить результат в уме.

Практические замечания

  • Тип операнда важен. Результат ~ зависит от разрядности типа: для byte (8 бит) и int (16 или 32 бита) результат будет разным. Если нужна инверсия только младших 8 бит, используйте явное приведение или маску: ~value & 0xFF.
  • Знаковый бит может удивить. Если переменная имеет тип int или long, инверсия затронет знаковый бит, и положительное число станет отрицательным. Это нормальное поведение, но важно учитывать его при сравнениях и арифметике.
  • Типичное применение — маски битов. Оператор ~ удобен в паре с &, когда нужно сбросить конкретный бит, не трогая остальные: PORTB &= ~(1 << 3) сбрасывает третий бит регистра PORTB.
  • Не путайте с логическим NOT. Оператор ! — это логическое отрицание: !0 даёт 1, а !5 даёт 0. Побитовый ~ работает с каждым битом числа, а не с его логическим смыслом.

Где применяется

  • Управление отдельными битами регистров — сброс нужного бита через маску вида ~(1 << N).
  • Работа с флагами — инверсия набора флагов для получения «всего, кроме выбранного».
  • Контрольные суммы и протоколы — некоторые протоколы передают инвертированный байт как проверочный.
  • Работа с PWM и ШИМ — получение дополнительного (инвертированного) сигнала для двухтактных схем.

Примечания и предупреждения

Знаковый бит в целочисленных типах со знаком может приводить к неожиданным результатам, если вы не учитываете дополнение до двух. Если результат ~x кажется неверным — проверьте тип переменной и при необходимости используйте unsigned-тип или явную маску, чтобы ограничить инверсию нужным числом бит.

Полезные материалы