Битовые флаги как аргументы функций на C / C++

Битовые флаги как аргументы функций на C / C++

Удобным решением для получения различного поведения от некоторой функции является использование битовых флагов, которые передаются ей в качестве входных параметров. Давайте разберемся, когда уместно применять и в чем заключается этот прием.

Постановка задачи

Предположим, нам нужна функция для управления светодиодными индикаторами клавиатуры (Scroll Lock, Num Lock и Caps Lock). Чтобы не усложнять приложение, реализуем его схематично. Будем выводить на консоль состояние, соответствующее переданным битовых флагам. Для этого используем следующую функцию:

[/crayon]
Если индикатор включен, то на консоли отобразится символ *, иначе _.

Применение битовых флагов

Первым делом определим следующее перечисление:

[/crayon]
Рядом с каждым значением в виде комментария мы указали его двоичное представление. Обратите внимание, что значения NUM_LOCK, CAPS_LOCK и SCROLL_LOCK выбраны таким образом, что единицы в их бинарном представлении не накладываются. Для определения этих значений мы использовали оператор бинарного сдвига << на один бит влево. Это означает, что бинарное умножение любого из них даст в результате ноль, то есть они в совокупности образуют набор битовых флагов.

Еще один интересный прием, который мы здесь наблюдаем, заключается в использовании комбинированного флага ALL. Он представляет собой побитовое сложение | всех возможных битовых флагов.

Реализуем саму функцию для установки состояния индикаторов:

[/crayon]
На вход она принимает параметр state. Проверка того, должен ли быть включен каждый индикатор или нет, осуществляется с помощью оператора побитового умножения &. Например, для CAPS_LOCK мы видим:

[/crayon]
Если биты в state и CAPS_LOCK наложатся, то в функцию printLEDState() будет передана истина, иначе ложь.

Рассмотрим пример, чтобы лучше понять, как это работает. Передадим функции setKeyboardLEDState() параметр state, равный NUM_LOCK | CAPS_LOCK (то есть 0001 | 0010 = 0011). Во время проверок state & NUM_LOCK ( 0011 & 0001 = 0001) и state & CAPS_LOCK ( 0011 & 0010 = 0010) мы видим, что единицы в бинарном представлении накладываются и получаются ненулевые значения, которые соответствуют true. Однако в последней проверке state & SCROLL_LOCK ( 0011 & 0100 = 0000) получается ноль, который соответствует false. В результате на экран будет выведено: * * _.

А вот еще несколько примеров запуска с указанием результатов, которые будут выведены на консоль:

[/crayon]

Заключение

Использование битовых флагов — довольно удобный и одновременно мощный прием. Его сильной чертой является возможность комбинирования различных режимов работы.

Понравилась статья? Поделиться с друзьями:
Добавить комментарий