Урок №39. Літерали і магічні числа

  Юрій  | 

  Оновл. 28 Кві 2020  | 

 232

У C++ є два види констант: літеральні і символьні. У цьому уроці ми розглянемо літеральні константи.

Літеральні константи

Літеральні константи (або просто “літерали”) — це значення, які вставляються безпосередньо в код. Оскільки вони є константами, то їх значення змінити не можна, наприклад:

З літералами типів bool і int все зрозуміло, а ось з літералами типу з плаваючою крапкою є два способи оголошення:

У другому способі оголошення, число після експонента може бути і від’ємним:

Числові літерали можуть мати суфікси, які визначають їх типи. Ці суфікси не є обов’язковими, так як компілятор розуміє з контексту, константу якого типу даних ви хочете використовувати.

Тип даних Суфікс Значення
int u чи U unsigned int
int l чи L long
int ul, uL, Ul, UL, lu, lU, Lu чи LU unsigned long
int ll чи LL long long
int ull, uLL, Ull, ULL, llu, llU, LLu чи LLU unsigned long long
double f чи F float
double l чи L long double

Суфікси є навіть для цілочисельних типів (але вони майже не використовуються):

За замовчуванням літеральні константи типу з плаваючою крапкою є типу double. Для конвертації літеральних констант в тип float, можна використовувати суфікс f або F:

C++ також підтримує літерали типів string і char:

Літерали добре використовувати в коді доти, доки їх значення зрозумілі й однозначні. Це виконання операцій присвоювання, математичних операцій або виведення тексту в консоль.

Літерали у вісімковій і шістнадцятковій системах числення

У повсякденному житті ми використовуємо десяткову систему числення, яка складається з десяти цифр: 0, 1, 2, 3, 4, 5, 6, 7, 8 і 9. За замовчуванням C++ використовує десяткову систему числення для чисел в програмах:

У двійковій (бінарній) системі числення всього 2 цифри: 0 і 1. Значення: 0, 1, 10, 11, 100, 101, 110, 111 і т.д.

Є ще дві інші системи числення: вісімкова і шістнадцяткова.

Вісімкова система числення складається з 8 цифр: 0, 1, 2, 3, 4, 5, 6 і 7. Значення: 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12 і т.д. (примітка: цифр 8 і 9 — немає, так що відразу перескакуємо з 7 до 10).

Десяткова система числення 0 1 2 3 4 5 6 7 8 9 10 11
Вісімкова система числення 0 1 2 3 4 5 6 7 10 11 12 13

Для використання літералу з вісімкової системи числення, використовуйте префікс 0 (нуль):

Результат виконання програми:

10

Чому 10 замість 12? Тому що std::cout виводить числа в десятковій системі числення, а 12 в вісімковій системі числення = 10 в десятковій системі числення.

Вісімкова система числення використовується дуже рідко.

Шістнадцяткова система числення складається з 16 символів: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, А, В, С, D, Е, F.

Десяткова система числення 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Шістнадцяткова система числення 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11

Для використання літералу з шістнадцяткової системи числення, використовуйте префікс 0x:

Результат виконання програми:

15

Оскільки в цій системі 16 символів, то одна шістнадцяткова цифра займає 4 біта. Отже, дві шістнадцяткові цифри займають 1 байт.

Розглянемо 32-бітне ціле число з двійкової системи числення: 0011 1010 0111 1111 1001 1000 0010 0110. Через довжину і повторення цифр його складно прочитати. У шістнадцятковій системі числення це ж значення буде виглядати наступним чином: 3A7F 9826. Такий зручний/стислий формат є перевагою шістнадцятковї системи числення. Тому шістнадцяткові значення часто використовуються для представлення адрес пам’яті або необроблених значень в пам’яті.

До C++14 використовувати літерал з двійкової системи числення було неможливо. Проте шістнадцяткова система числення може нам в цьому допомогти:

Бінарні літерали і розділювач цифр в C++14

В C++14 ми можемо використовувати бінарні (двійкові) літерали, додаючи префікс 0b:

Оскільки довгі літерали читати важко, то в C++14 додали можливість використовувати одинарну лапку ' як розділювач цифр:

Якщо ваш компілятор не підтримує C++14, то використовувати бінарні літерали і розділювач цифр ви не зможете — компілятор видасть помилку.

Магічні числа. Що з ними не так?

Розглянемо наступний фрагмент коду:

В наведеному вище прикладі число 30 є магічним числом. Магічне число — це добре закодований літерал (зазвичай, число) в рядку коду, який не має ніякого контексту. Що це за 30, що воно означає/позначує? Хоча з прикладу вище можна здогадатися, що число 30 означає максимальну кількість учнів, які перебувають в одному кабінеті, в більшості випадків, це не завжди буде настільки очевидним і зрозумілим. У більш складних програмах контекст подібних чисел розгадати набагато складніше (якщо тільки не буде відповідних коментарів).

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

Розглянемо наступний фрагмент коду:

Щоб оновити число учнів в кабінеті, нам потрібно змінити значення константи з 30 на 36. Але що робити з викликом функції setMax(30)? Аргумент 30 і константа 30 в коді вище є одним і тим же, вірно? Якщо так, то нам потрібно буде оновити це значення. Якщо ні, то нам не слід взагалі чіпати цей виклик функції. Якщо ж проводити автоматичний глобальний пошук і заміну числа 30, то можна ненароком змінити і аргумент функції setMax(), в той час, коли його взагалі не слід було б чіпати. Тому вам доведеться переглянути весь код “вручну”, в пошуках числа 30, а потім, в кожному конкретному випадку, визначитись: змінювати 30 на 36 чи ні. Це може зайняти дуже багато часу + ймовірність виникнення нових помилок підвищується в рази.

На щастя, є кращий варіант — використовувати символьні константи. Про них ми поговоримо в наступному уроці.

Правило: Намагайтеся скоротити до мінімуму використання магічних чисел в ваших програмах.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (1 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *