Бьерн Страуструп - Язык программирования С++. Главы 2-4 - Поразрядные логические операции

ОГЛАВЛЕНИЕ

 

3.2.4  Поразрядные логические операции

Поразрядные логические операции

      &    |    ^    ~    >>    <<

применяются к целым, то есть к объектам типа char, short, int, long и к их беззнаковым аналогам. Результат операции также будет целым.

Чаще всего поразрядные логические операции используются для работы с небольшим по величине множеством данных (массивом разрядов). В этом случае каждый разряд беззнакового целого представляет один элемент множества, и число элементов определяется количеством разрядов. Бинарная операция & интерпретируется как пересечение множеств, операция | как объединение, а операция ^ как разность множеств. С помощью перечисления можно задать имена элементам множества. Ниже приведен пример, заимствованный из <iostream.h>:

         class ios {
         public:
            enum io_state {
                 goodbit=0, eofbit=1, failbit=2, badbit=4
            };
            // ...
         };

Состояние потока можно установить следующим присваиванием:

         cout.state = ios::goodbit;

Уточнение именем ios необходимо, потому что определение io_state находится в классе ios, а также чтобы не возникло коллизий, если пользователь заведет свои имена наподобие goodbit.

Проверку на корректность потока и успешное окончание операции можно задать так:

        if (cout.state&(ios::badbit|ios::failbit))  // ошибка в потоке

Еще одни скобки необходимы потому, что операция & имеет более высокий приоритет, чем операция "|".

Функция, обнаружившая конец входного потока, может сообщать об этом так:

        cin.state |= ios::eofbit;

Операция |= используется потому, что в потоке уже могла быть ошибка (т.е. state==ios::badbit), и присваивание

        cin.state =ios::eofbit;

могло бы затереть ее признак. Установить отличия в состоянии двух потоков можно следующим способом:

       ios::io_state diff = cin.state^cout.state;

Для таких типов, как io_state, нахождение различий не слишком полезная операция, но для других сходных типов она может оказаться весьма полезной. Например, полезно сравнение двух  разрядных массива, один из которых представляет набор всех возможных обрабатываемых прерываний, а другой - набор прерываний, ожидающих обработки.

Отметим, что использование полей ($$R.9.6) может служить удобным и более лаконичным способом работы с частями слова, чем сдвиги и маскирование. С частями слова можно работать и с помощью поразрядных логических  операций. Например, можно выделить средние 16 разрядов из средины 32-разрядного целого:

      unsigned short middle(int a) { return (a>>8)&0xffff; }

Только не путайте поразрядные логические операции с просто логическими операциями:

              &&    ||    !

Результатом последних может быть 0 или 1, и они в основном используются в условных выражениях операторов if, while или for ($$3.3.1).  Например,  !0 (не нуль) имеет значение 1, тогда как ~0 (дополнение нуля) представляет собой набор разрядов "все единицы", который обычно является значением -1 в дополнительном коде.