Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

10.4. Бітові поля структур

На відміну від багатьох інших комп'ютерних мов, у мові C++ передбачено вбудований спосіб доступу до конкретного розряду байта. Побітовий доступ можливий шляхом використання бітових полів. Бітові поля можуть виявитися корисними в різних ситуаціях. Наведемо всього три приклади:

  • по-перше, якщо ми маємо справу з обмеженим об'ємом пам'яті, можна зберігати декілька булевих (логічних) значень в одному байті;

  • по-друге, деякі інтерфейси пристроїв передають інформацію, закодовану саме в бітах;

  • по-третє, існують підпрограми кодування, яким потрібен доступ до окремих бітів у рамках байта.

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

Бітове поле – це біт-орієнтований член структури.

Метод, який використовується у мові C++ для доступу до бітів, базується на застосуванні структур. Бітове поле – це спеціальний тип члена структури, який визначає свій розмір у бітах. Загальний формат визначення бітових полів є таким:

struct ім'я_типу_структури {

тип ім'я_1: довжина;

тип ім'я_2: довжина;

. . . . . . . .

тип ім'я_n|: довжина;

};

У цьому записі елемент тип означає тип бітового поля, а елемент довжинакількість бітів у цьому полі. Бітове поле повинно бути оголошено як значення цілочисельного типу або перерахунку. Бітові поля завдовжки 1 біт оголошуються як значення типу без знаку (unsigned), оскільки єдиний біт не може мати знакового розряду.

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

Біт

Значення у встановленому стані

0

Зміна в лінії установки в початковий стан

1

Зміна в лінії готовності даних

2

Виявлений задній фронт

3

Зміна в лінії прийому даних

4

Встановлення в початковий стан

5

Дані готові

6

Телефонний сигнал виклику

7

Сигнал прийнято

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

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 << "Дані готові";

Щоб присвоїти бітовому полю значення, достатньо використовувати таку ж форму, яка зазвичай застосовується для елемента структури будь-якого іншого типу. Наприклад, настанова

status.ring = 0;

очищає бітове поле ring. Як видно з цих прикладів, доступ до кожного бітового поля можна отримати за допомогою оператора "крапка". Але, якщо загальний доступ до структури здійснюється через покажчик, необхідно використовувати оператор "->".

Потрібно мати на увазі, що зовсім необов'язково присвоювати ім'я кожному бітовому полю. Це дає змогу звертатися тільки до потрібних бітів, "обходячи" інші. Наприклад, якщо нас цікавлять тільки біти cts і dsr, то ми могли б оголосити структуру status_type так:

struct status_type {

unsigned: 4;

unsigned cts: 1;

unsigned dsr: 1;

} status;

Необхідно звернути тут увагу на те, що біти після останнього іменованого dsr немає потреби взагалі згадувати.

У структурі можна змішувати "звичайні" члени з бітовими полями. Наприклад,:

struct empStruct {

struct addrStruct address;

float pay;

unsigned lay_off: 1; // працює чи ні

unsigned hourly: 1; // погодинна оплата або оклад

unsigned deductions: 3; // утримання податку

};

Ця структура визначає запис по кожному службовцю, у якій використовується тільки один байт для зберігання трьох елементів інформації: статус службовця, характер оплати його праці (погодинна оплата або фіксований оклад) і податкова ставка. Без використання бітових полів для зберігання цієї інформації довелося б зайняти три байти.

Використання бітових полів має певні обмеження. Програміст не може отримати адресу бітового поля або посилання на нього. Бітові поля не можна зберігати в масивах. Їх не можна оголошувати статичними. При переході від одного комп'ютера до іншого неможливо знати впевнено порядок проходження бітових полів: справа наліво або зліва направо. Це означає, що будь-яка програма, у якій використовуються бітові поля, може страждати певною залежністю від марки комп'ютера. Можливі і інші обмеження, пов'язані з особливостями реалізації компілятора мови C++. Тому, перш ніж використовувати бітові поля структур, доцільно насамперед з'ясувати ці питання у відповідній документації до Вашого компілятора.

У наступному підрозділі представлено код програми (прог. 10.8), у якому для відображення символьних ASCII-кодів у двійковій системі числення використовуються бітові поля.