Литмир - Электронная Библиотека
A
A

Следует подчеркнуть, что оператор

&
отличается от оператора
&&
, а оператор
|
отличается от оператора
||
тем, что они применяются к каждому биту своих операндов по отдельности (раздел A.5.5), а их результат состоит из такого же количества битов, что и операнды. В противоположность этому операторы
&&
и
||
просто возвращают значение
true
или
false
.

Рассмотрим несколько примеров. Обычно битовые комбинации выражаются в шестнадцатеричном виде. Для полубайта (четыре бита) используются следующие коды.

Программирование. Принципы и практика использования C++ Исправленное издание - _315.png

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

Программирование. Принципы и практика использования C++ Исправленное издание - _316.png

Итак, используя для простоты тип

unsigned
(раздел 25.5.3), можем написать следующий фрагмент кода:

unsigned char a = 0xaa;

unsigned char x0 = ~a; // дополнение a

Программирование. Принципы и практика использования C++ Исправленное издание - _317.png

unsigned char b = 0x0f;

unsigned char x1 = a&b; // a и b

Программирование. Принципы и практика использования C++ Исправленное издание - _318.png

unsigned char x2 = a^b; // исключительное или: a xor b

Программирование. Принципы и практика использования C++ Исправленное издание - _319.png

unsigned char x3 = a<<1; // сдвиг влево на один разряд

Программирование. Принципы и практика использования C++ Исправленное издание - _320.png

Вместо бита, который был “вытолкнут” с самой старшей позиции, в самой младшей позиции появляется нуль, так что байт остается заполненным, а крайний левый бит (седьмой) просто исчезает.

unsigned char x4 == a>>2; // сдвиг вправо на два разряда

Программирование. Принципы и практика использования C++ Исправленное издание - _321.png

В двух позициях старших битов появились нули, которые обеспечивают заполнение байта, а крайние правые биты (первый и нулевой) просто исчезают.

Мы можем написать много битовых комбинаций и потренироваться в выполнении операций над ними, но это занятие скоро наскучит. Рассмотрим маленькую программу, переводящую целые числа в их битовое представление.

int main()

{

  int i;

  while (cin>>i)

    cout << dec << i << "=="

         << hex << "0x" << i << "=="

         << bitset<8*sizeof(int)>(i) << '\n';

}

Для того чтобы вывести на печать отдельные биты целого числа, используется класс

bitset
из стандартной библиотеки.

bitset<8*sizeof(int)>(i)

Класс

bitset
хранит фиксированное количество битов. В данном случае мы использовали количество битов, равное размеру типа int —
8*sizeof(int)
, — и инициализировали объект класса
bitset
целым числом
i
.

ПОПРОБУЙТЕ

Скомпилируйте программу для работы с битовыми комбинациями и попробуйте создать двоичные и шестнадцатеричные представления нескольких чисел. Если вас затрудняет представление отрицательных чисел, перечитайте раздел 25.5.3 и попробуйте снова.

25.5.2. Класс bitset

Для представления наборов битов и работы с ними используется стандартный шаблонный класс

bitset
из заголовка
<bitset>
. Каждый объект класса
bitset
имеет фиксированный размер, указанный при его создании.

bitset<4> flags;

bitset<128> dword_bits;

bitset<12345> lots;

Объект класса

bitset
по умолчанию инициализируется одними нулями, но обычно у него есть инициализатор. Инициализаторами объектов класса
bitset
могут быть целые числа без знака или строки, состоящие из нулей и единиц:

bitset<4> flags = 0xb;

bitset<128> dword_bits(string("1010101010101010"));

bitset<12345> lots;

Здесь объект

lots
будет содержать одни нули, а
dword_bits
— 112 нулей, за которыми следуют 16 явно заданных битов. Если вы попытаетесь проинициализировать объект класса
bitset
строкой, состоящей из символов, отличающихся от
'0'
и
'1'
, то будет сгенерировано исключение
std::invalid_argument
.

string s;

cin>>s;

bitset<12345> my_bits(s); // может генерировать исключение

                          // std::invalid_argument

К объектам класса

bitset
можно применять обычные операции над битами. Предположим, что переменные
b1
,
b2
и
b3
являются объектами класса
bitset
.

357
{"b":"847443","o":1}