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

9.3. Порозрядні оператори

Оскільки мова C++ спрямована на те, щоб відкрити повний доступ до апаратних засобів комп'ютера, важливо, щоб оператор мав можливість безпосередньо впливати на окремі біти у межах байта або машинного слова. Саме тому мова програмування C++ і містить порозрядні оператори, призначені для тестування, встановлення або зсуву реальних бітів у байтах або словах, які відповідають символьним або цілочисельним С++-типам даних. Порозрядні оператори не використовуються для операндів типу bool, float, double, long double, void або інших ще складніших типів даних.

Порозрядні оператори обробляють окремі біти.

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

Табл. 9.1. Порозрядні оператори оброблення окремих бітів

Оператор

Значення

&

Порозрядне І (AND)

Порозрядне АБО (OR)

^

Порозрядне виключення АБО (ХОR)

>>

Зсув вправо

<<

Зсув вліво

~

Доповнення до І (унарний оператор НЕ)

9.3.1. Порозрядні оператори і, або, що виключає або і не

Порозрядні оператори І, АБО, що виключають АБО і НЕ (що позначаються символами &, |, ^ і ~ відповідно) виконують ті самі операції, що і їх логічні еквіваленти (тобто вони діють згідно з тією ж таблицею істинності). Відмінність полягає тільки у тому, що порозрядні операції працюють на побітовій основі. У наведеній нижче таблиці показано результат виконання кожної порозрядної операції для всіх можливих поєднань операндів (нулів і одиниць).

Табл. 9.1. Результат виконання порозрядних операцій поєднань операндів

р

q

р & q

р | а

р ^ а

~р

0

0

0

0

0

1

1

0

0

1

1

0

0

1

0

1

1

1

1

1

1

1

0

0

Як видно з цієї таблиці, результат застосування оператора ХОR (що виключає АБО) буде дорівнювати значенню ІСТИНА (1) тільки у тому випадку, якщо істинний (дорівнює значенню 1) тільки один з операндів; інакше результат приймає значення ФАЛЬШ (0).

Порозрядний оператор І можна представити як спосіб придушення бітової інформації. Це означає, що 0 в будь-якому операнді забезпечить установку в 0 відповідного біта результату. Ось приклад:

1101 0011

& 1010 1010

1000 0010

Наведений нижче код програми зчитує символи з клавіатури і перетворює будь-який рядковий символ в його прописний еквівалент шляхом встановлення шостого біта, що дорівнює значенню 0. Набір символів ASCII визначено так, що рядкові букви мають майже такий самий код, що і прописні, за винятком того, що код перших відрізняється від коду програми інших точно на 32. Отже, як це показано у наведеному нижче коді програми, щоб з рядкової букви зробити прописну, достатньо очистити її шостий біт.

Код програми 9.7. Демонстрація перетворення рядкових букв у прописні

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

int main()

{

char ch;

do {

cin >> ch;

// Ця настанова онулює 6-й біт.

ch = ch & 223; // В змінної ch тепер прописна буква.

cout << ch;

} while(ch !='Q');

getch(); return 0;

}

Значення 223, що використовується в настанові порозрядного І, є десятковим представленням двійкового числа 1101 1111. Отже, ця операція І залишає всі біти в змінній ch незайманими, за винятком шостого (він скидається в нуль).

Оператор І також корисно використовувати, якщо потрібно визначити, чи встановлено біт, який Вас зацікавив, тобто чи дорівнює він значенню 1 чи ні. Наприклад, у процесі виконання такої настанови можна дізнатися, чи встановлено 4-й біт у змінній status:

if(status & 8) cout << "Біт 4 встановлено";

Щоб зрозуміти, чому для тестування четвертого біта використовують число 8, пригадаймо, що в двійковій системі числення число 8 представляється як 0000 1000, тобто в числі 8 встановлено тільки четвертий розряд. Тому умовний вираз у настанові if дасть значення ІСТИНА тільки у тому випадку, якщо четвертий біт змінної status також встановлено (дорівнює 1). Цікаве використання цього методу показано на прикладі функції disp_binary(). Вона відображає в двійковому форматі конфігурацію бітів свого аргументу. Будемо використовувати функцію disp_binary() нижче у цьому підрозділі для дослідження можливостей інших порозрядних операцій:

// Відображення конфігурації бітів у байті

void disp_binary(unsigned u)

{

register int t;

for(t=128; t>0; t = t/2)

if(u & t) cout << "1 ";

else cout << "0 ";

cout << "\n";

}

Функція disp_binary(), використовуючи порозрядний оператор І, послідовно тестує кожен біт молодшого байта змінної u, щоб визначити, встановлений він чи скинутий. Якщо він встановлений, то відображається цифра 1, інакше цифра 0. Заради інтересу спробуйте розширити цю функцію так, щоб вона відображала всі біти змінної І, а не тільки її молодший байт.

Порозрядний оператор АБО, на противагу порозрядному оператору І, зручно використовувати для встановлення потрібних бітів у одиницю. У процесі виконання операції АБО наявність в будь-якому операнді біта, що дорівнює 1, означає, що в результаті відповідний біт також буде дорівнювати одиниці. Ось приклад.

1101 0011

| 1010 1010

1111 1011

Можна використовувати оператор АБО для перетворення розглянутої вище програми (яка перетворить рядкові символи в їх прописні еквіваленти) в її "протилежність", тобто тепер, як це показано нижче, вона перетворюватиме прописні букви у рядкові.

Код програми 9.8. Демонстрація перетворення прописних букв у рядкові

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

int main()

{

char ch;

do {

cout << "Введіть прописну букву: "; cin >> ch;

/* Ця настанова робить букву рядковою,

встановлюючи її 6-й біт. */

ch = ch | 32;

cout << "\nРядкова буква: " << ch << "\n";

} while(ch != 'q');

getch(); return 0;

}

Встановлення шостого біта перетворює прописну букву на її рядковий еквівалент.

Порозрядне виключення АБО (ХОR) встановлює в одиницю біт результату тільки у тому випадку, якщо відповідні біти операндів відрізняються один від одного, тобто вони є не однаковими. Ось приклад:

0111 1111

^ 1011 1001

1100 0110

Унарний оператор НЕ (або оператор доповнення до 1) інвертує стан усіх бітів свого операнда. Наприклад, якщо цілочисельне значення (що зберігається в змінній А), є двійковим кодом 1001 0110, то в результаті виконання операції ~А отримаємо двійковий код 0110 1001.

У наведеному нижче коді програми продемонстровано механізм використання оператора НЕ шляхом відображення деякого числа і його доповнення до 1 у двійковому коді за допомогою наведеної вище функції disp_binary().

Код програми 9.9. Демонстрація механізму використання оператора НЕ

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

void disp_binary(unsigned u);

int main()

{

unsigned u;

cout << "Введіть число між 0 і 255: "; cin >> u;

cout << "Початкове число в двійковому коді: ";

disp_binary(u);

cout << "Його доповнення до одиниці: ";

disp_binary(~u);

getch(); return 0;

}

// Відображення бітів, з яких складається байт.

void disp_binary(unsigned u)

{

register int t;

for(t=128; t>0; t = t/2)

if(u & t) cout << "1 ";

else cout << "0 ";

cout << "\n";

}

Ось як виглядають результати виконання цієї програми.

Введіть число між 0 і 255: 99

Початкове число в двійковому коді: 01100011

Його доповнення до одиниці: 10011100

Варто знати! Не плутайте логічні та порозрядні оператори. Вони виконують різні дії. Оператори &, | і ~ застосовуються безпосередньо до кожного біта значення окремо. Еквівалентні логічні оператори обробляють як операнди значення ІСТИНА/ФАЛЬШ (не нуль/нуль). Тому порозрядні оператори не можна використовувати замість їх логічних еквівалентів у умовних виразах. Наприклад, якщо значення х дорівнює 7, то вираз x && 8 має значення ІСТИНА, тоді як вираз x & 8 дає значення ФАЛЬШ.

Необхідно пам'ятати! Оператор відношення або логічний оператор завжди генерує результат, який має значення ІСТИНА або ФАЛЬШ, тоді як аналогічний порозрядний оператор генерує значення, що отримується згідно з таблицею істинності конкретної операції.