flags = flags & MASK;
приведет к установке всех битов flags (кроме первого) в 0, т.к. любой бит, объединяемый с 0 посредством операции “И”, дает 0. Бит номер 1 переменной остается неизменным. (Если бит равен 1, то значением 1 & 1 будет 1; если же бит равен 0, то 0 & 1 дает 0.) Такой процесс называется “использованием маски”, поскольку нули в маске скрывают соответствующие биты в переменной flags.
Развивая аналогию, биты с 0 в маске можно считать непрозрачными, а биты с 1 - прозрачными. Выражение flags & MASK похоже на накрывание маской комбинации битов flags; видимыми из-под маски будут только те биты, которым в MASK соответствуют биты с 1 (рис. 15.2).
Манипулирование битами 635

Рис. 15.2. Наглядное представление маски
Для сокращения кода можно применить операцию “И”, объединенную с присваиванием:
flags &= MASK;
Ниже показан один распространенный случай использования этой операции:
ch &= 0xff; /* или ch &= 0377; */
Вспомните, что значение 0xff записывается как 11111111 в двоичном или как 0377 в восьмеричном виде. Эта маска оставляет последние восемь битов в ch без изменений, а остальные устанавливает в 0. Независимо от того, сколько битов содержит исходная переменная ch — 8, 16 или более, — финальное значение усекается до величины, которая умещается в один 8-битовый байт. В данном случае маска имеет ширину 8 битов.
Случай применения: включение (установка) битов
Иногда требуется включить отдельные биты в значении, оставив остальные без изменений. Например, компьютер IBM PC управляет оборудованием, отправляя нужные значения в порты. Для активизации, скажем, динамика, необходимо включить бит 1, а остальные биты оставить неизменными. Этого можно сделать с помощью побитовой операции “ИЛИ”.
Например, пусть имеется константа MASK, в которой бит 1 установлен в 1. Тогда оператор
flags = flags | MASK;
включает бит номер 1 в переменной flags и оставляет все остальные биты без изменений. Это объясняется тем, что любой бит, объединенный с 0 посредством операции , остается самим собой, а объединенный с 1 с использованием I, становится равным 1.
Например, пусть flags равно 00001111 и MASK — 10110110. Выражение
flags | MASK становится
(00001111) | (10110110) // выражение
и после вычисления дает следующий результат:
(10111111) // результат
636 Глава 15
Все биты, установленные в 1 внутри MASK, также будут установлены в 1 в результате. Все биты в flags, которые соответствуют битам 0 в MASK, остаются неизмененными.
Для краткости можно использовать побитовую операцию “ИЛИ”, объединенную с присваиванием:
flags |= MASK;
Этот оператор установит в 1 те биты falgs, которым соответствуют включенные биты в MASK, оставив другие биты без изменений.
Случай применения: выключение (очистка) битов
Точно так же, как удобно иметь возможность включать отдельные биты, не затрагивая остальные, не менее удобно располагать возможностью их выключения. Предположим, что требуется отключить бит номер 1 в переменной flags. И снова MASK имеет включенный только бит 1. Можно воспользоваться следующим оператором:
flags = flags & ~MASK;
Поскольку в MASK все биты кроме бита 1 выключены, выражение -MASK дает значение, в котором все биты кроме бита 1 включены. Объединение 1 с любым битом, используя операцию &, дает сам этот бит, поэтому оператор оставляет все биты кроме бита 1 без изменений. Объединение 0 с любым битом посредством операции & дает О независимо от исходного значения бита.
Например, пусть flags равно 00001111 и MASK — 10110110. Выражение
flags & ~MASK становится
(00001111) & ^(10110110) // выражение
и после вычисления дает следующий результат:
(00001001) // результат
Все биты, установленные в 1 внутри MASK, будут установлены в 0 в результате. Все биты в flags, которые соответствуют битам 0 в MASK, остаются неизмененными.
Ниже представлена сокращенная форма:
flags &= -MASK;
Случай применения: переключение битов
Переключение бита означает его выключение, если он включен, и включение, если выключен. Для переключения битов можно применять побитовую операцию исключающего “ИЛИ”. Идея в том, что если b — это установленное состояние бита (1 или 0), то 1 ^b равно 0, когда b равно 1, и 1, когда b равно 0. Кроме того, выражение 0 ^b дает b независимо от значения b. Следовательно, в результате объединения значения с маской с использованием операции ^биты, соответствующие 1 в маске, переключаются, а биты, соответствующие 0 в маске, останутся неизмененными. Чтобы переключить бит 1 переменной flags, можно выполнить одно из следующих действий:
Читать дальше