3.2.4 Побитовые логические операции
3.2.4 Побитовые логические операции
Побитовые логические операции
amp; ! ^ ~ »» ««
применяются к целым, то есть к объектам типа char, short, int, long и их unsigned аналогам, результаты тоже цлые.
Одно из стандартных применений побитовых логических опраций – реализация маленького множества (вектор битов). В этом случае каждый бит беззнакового целого представляет один член множества, а число членов ограничено числом битов. Бнарная операция amp; интерпретируется как пересечение, ! как объединение, а ^ как разность. Для наименования членов такого множества можно использовать перечисление. Вот маленький прмер, заимствованный из реализации (не пользовательского итерфейса) «stream.h»:
enum state_value (* _good=0, _eof=1, _fail=2, _bad=4 *); // хорошо, конец файла, ошибка, плохо
Определение _good не является необходимым. Я просто хтел, чтобы состояние, когда все в порядке, имело подходящее имя. Состояние потока можно установить заново следующим обрзом:
cout.state = _good;
Например, так можно проверить, не был ли испорчен поток или допущена операционная ошибка:
if (cout.state amp;(_bad!_fail)) // не good
Еще одни скобки необходимы, поскольку amp; имеет более всокий приоритет, чем !.
Функция, достигающая конца ввода, может сообщать об этом так:
cin.state != _eof;
Операция != используется потому, что поток уже может быть испорчен (то есть, state==_bad), поэтому
cin.state = _eof;
очистило бы этот признак. Различие двух потоков можно находить так:
state_value diff = cin.state^cout.state;
В случае типа stream_state (состояние потока) такая раность не очень нужна, но для других похожих типов она оказвается самой полезной. Например, при сравнении вектора бит, представляющего множество прерываний, которые обрабатываются, с другим, представляющим прерывания, ждущие обработки.
Следует заметить, что использование полей (#2.5.1) в действительности является сокращенной записью сдвига и маскрования для извлечения полей бит из слова. Это, конечно, моно сделать и с помощью побитовых логических операций, Например, извлечь средние 16 бит из 32-битового int можно следующим образом:
unsigned short middle(int a) (* return (a»»8) amp;0xffff; *)
Не путайте побитовые логические операции с логическими операциями:
amp; amp; !! !
Последние возвращают 0 или 1, и они главным образом ипользуются для записи проверки в операторах if, while или for (#3.3.1). Например, !0 (не ноль) есть значение 1, тогда как ~ 0 (дополнение нуля) есть набор битов все-единицы, который обычно является значением -1.