В отличие от многих других компьютерных языков, в C++ предусмотрен встроенный способ доступа к конкретному разряду байта. Побитовый доступ возможен путем использования битовых полей. Битовые поля могут оказаться полезными в различных ситуациях. Приведем всего три примера. Во-первых, если вы имеете дело с ограниченным объемом памяти, можно хранить несколько булевых (логических) значений в одном байте. Во-вторых, некоторые интерфейсы устройств передают информацию, закодированную именно в битах. И, в-третьих, существуют подпрограммы кодирования, которым нужен доступ к отдельным битам в рамках байта. Реализация всех этих функций возможна с помощью поразрядных операторов, как было показано в предыдущей главе, но битовое поле может сделать вашу программу более прозрачной и читабельной, а также повысить ее переносимость.

Метод, который использован в языке C++ для доступа к битам, основан на применении структур. Битовое поле — это в действительности специальный тип члена структуры, который определяет свой размер в битах. Общий формат определения битовых полей таков.

struct имя_типа_структуры {

 тип имя1 : длина;

 тип имя2 : длина;

 .

 .

 .

 тип имяN : длина;

};

Здесь элемент тип означает тип битового поля, а элемент длина — количество битов в этом поле. Битовое поле должно быть объявлено как значение целочисленного типа или перечисления. Битовые поля длиной 1 бит объявляются как значения типа без знака (unsigned), поскольку единственный бит не может иметь знакового разряда.

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

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

struct status_type {

 unsigned delta_cts: 1;

 unsigned delta_dsr: 1;

 unsigned tr_edge: 1;

 unsigned delta_rec: 1;

 unsigned cts: 1;

 unsigned dsr: 1;

 unsigned ring: 1;

 unsigned rec_line: 1;

} status;

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

status = get_port_status();

if(status.cts) cout << "Установка в исходное состояние";

if(status.dsr) cout << "Данные готовы";

Чтобы присвоить битовому полю значение, достаточно использовать такую же форму, которая обычно применяется для элемента структуры любого другого типа. Например, следующая инструкция очищает битовое поле ring:

status.ring = 0;

Как видно из этих примеров, доступ к каждому битовому полю можно получить с помощью оператора "точка". Но если общий доступ к структуре осуществляется через указатель, необходимо использовать оператор "->".

Следует иметь в виду, что совсем необязательно присваивать имя каждому битовому полю. Это позволяет обращаться только к нужным битам, "обходя" остальные. Например, если вас интересуют только биты cts и dsr, вы могли бы объявить структуру status_type следующим образом.

struct status_type {

 unsigned : 4;

 unsigned cts: 1;

 unsigned dsr: 1;

} status;

Обратите здесь внимание на то, что биты после последнего именованного dsr нет необходимости вообще упоминать.

В структуре можно смешивать "обычные" члены с битовыми полями. Вот пример.

struct emp {

 struct addr address;

 float pay;

 unsigned lay_off: 1; // работает или нет

 unsigned hourly: 1: // почасовая оплата или оклад

 unsigned deductions: 3: // удержание налога

};

Эта структура определяет запись по каждому служащему, в которой используется только один байт для хранения трех элементов информации: статус служащего, характер оплаты его труда (почасовая оплата или твердый оклад) и налоговая ставка. Без использования битовых полей для хранения этой информации пришлось бы занять три байта.

Перейти на страницу:

Все книги серии Изучайте C++ с профессионалами

Похожие книги