В С++ существуют следующие побитовые (поразрядные) операции:
- унарная операция поразрядного отрицания (дополнение) – '~';
- бинарная операция поразрядного И (умножение) – '&';
- бинарная операция поразрядного ИЛИ (сложение) – '|';
- бинарная операция поразрядного исключающего ИЛИ (XOR) – '^';
Операнды поразрядных операций могут быть любого целого типа.
Операция ~инвертирует операнд, т.е. меняет в его битовом представлении все 0 на 1, а все 1 – на 0.
Операция & сравнивает каждый бит первого операнда с соответствующим битом второго операнда. Если оба соответствующих бита – единицы, то соответствующий бит результата устанавливается в 1, в противном случае в 0.
Операция |сравнивает каждый бит первого операнда с соответствующим битом второго операнда; если хотя бы один из них равен 1, то соответствующий бит результата устанавливается в 1, в противном случае – в 0.
Операция ^. Если сравниваемые биты одинаковы, то результат устанавливается в 0, если различны – в 1.
Пример побитовых операций:
short a = 0x45FF;
short b = 255; // 0xFF short c; c = a ^ b; // c: 0x4500 c = a | b; // c: 0x45FF c = a & b; // c: 0x00FF c = ~ a; // c: 0xBA00
Этот фрагмент программы можно проиллюстрировать так:
a
b
a ^ b
a | b
a & b
~a
Поразрядные операции часто используются для создания битовых масок, которые позволяют компактно хранить набор флагов (значения логического типа, равные true или false) в одной переменной.
В этом случае для работы с маской используются следующие операции:
- для установки флага – '|';
- для проверки установлен ли флаг – '&';
- для снятия флага – '~' вместе с '&'.
Например, пусть нужно хранить набор прав доступа к файлу для пользователя-владельца и всех остальных пользователей:
// Объявляем флаги с возможными правами доступа
char usr_exec = 1; // Пользователь может выполнять файл (0000 0001)
//Проверяем установлен ли флаг other_write и если да – снимаем его
if (rights & other_write) // rights & other_write = 0001 0000 (true)
rights &= ~other_write; // rights = 00000101
Сдвиги
Операции сдвига << и >> осуществляют соответственно сдвиг влево и вправо своего левого операнда на число битовых позиций, заданных правым операндом. Таким образом, Х << n возвращает значение Х, сдвинутое влево на n позиций, заполняя освобождающиеся биты нулями. При этом теряются n старших битов.
Сдвиг вправо величины без знака сопровождается дополнением старших битов нулями. Если сдвигается значение со знаком, то результат сдвига определяется реализацией. В любом случае n младших битов теряются.
Операции сдвига не изменяют значение, хранящееся в X (в левом операнде).
Правый операнд должен быть константным выражением, т.е. выражением, включающим в себя только константы. Если правый операнд отрицателен или он больше или равен числу битов левого операнда, то результат сдвига не определён.