Урок №35. Фіксований розмір цілочисельних типів даних

  Юрій  | 

  Оновл. 23 Лип 2021  | 

 208

На уроці про цілочисельні типи даних ми говорили, що мова C++ гарантує тільки їх мінімальний розмір — вони ж можуть займати і більше, в залежності від компілятора і/або архітектури комп’ютера.

Чому розмір всіх цілочисельних типів не є фіксованим?

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

Цілочисельні типи фіксованого розміру

Щоб вирішити питання кросплатформенності, в мові С++ додали набір цілочисельних типів фіксованого розміру, які гарантовано мають один і той же розмір на будь-якій архітектурі:

Назва Тип Діапазон значень
int8_t 1 байт signed від -128 до 127
uint8_t 1 байт unsigned від 0 до 255
int16_t 2 байти signed від -32 768 до 32 767
uint16_t 2 байти unsigned від 0 до 65 535
int32_t 4 байти signed від -2 147 483 648 до 2 147 483 647
uint32_t 4 байти unsigned від 0 до 4 294 967 295
int64_t 8 байт signed від -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
uint64_t 8 байт unsigned від 0 до 18 446 744 073 709 551 615

Починаючи з C++11 доступ до цих типів здійснюється через підключення заголовку cstdint (знаходяться ці типи даних в просторі імен std). Розглянемо приклад на практиці:

Оскільки цілочисельні типи фіксованого розміру були додані ще до C++11, то деякі старі компілятори надають доступ до них через підключення заголовку stdint.h.

Якщо ваш компілятор не підтримує cstdint чи stdint.h, то ви можете завантажити кросплатформний заголовковий файл pstdint.h. Просто підключіть його до вашого проекту, і він самостійно визначить цілочисельні типи фіксованого розміру для вашої системи/архітектури.

Попередження щодо std::int8_t і std::uint8_t

З певних причин в мові C++ більшість компіляторів визначають і обробляють типи int8_t і uint8_t ідентично типам char signed і char unsigned, але це відбувається далеко не у всіх випадках. Отже, std::cin і std::cout можуть працювати не так, як ви очікуєте. Наприклад:

На більшості архітектур результат виконання цієї програми наступний:

A

Тобто вищенаведена програма опрацьовує myint як змінну типу char. Однак на деяких комп’ютерах результат може бути наступним:

65

Тому ідеальним варіантом буде уникати використання std::int8_t і std::uint8_t взагалі (використовуйте замість них std::int16_t або std::uint16_t). Однак, якщо ви використовуєте std::int8_t або std::uint8_t, то ви повинні бути обережні з будь-якою функцією, яка може інтерпретувати std::int8_t або std::uint8_t в символьний тип даних, замість цілочисельного (наприклад, з об’єктами std::cin і std::cout).

Правило: Уникайте використання std::int8_t і std::uint8_t. Якщо ви використовуєте ці типи, то будьте уважні, так як в деяких випадках вони можуть оброблятися як тип char.

Недоліки цілочисельних типів фіксованого розміру

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

Суперечка щодо unsigned

Багато розробників (і навіть великі організації) вважають, що програмісти повинні уникати використання цілочисельних типів unsigned взагалі. Головна причина — це непередбачувана поведінка і результати, які можуть виникнути при “змішуванні” цілочисельних типів signed і unsigned в програмі.

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

Що станеться в цьому випадку? -1 перетвориться в інше велике число (швидше за все в 4 294 967 295). Але весь біль полягає в тому, що запобігти цьому ми не можемо. Мова C++ вільно конвертує числа з типів unsigned в типи signed і навпаки без перевірки діапазону допустимих значень певного типу даних. А це, в свою чергу, може призвести до переповнення.

Б’ярн Страуструп, творець мови C++, казав: “Використовувати тип unsigned (замість signed) для отримання ще одного біта для представлення додатних цілих чисел, майже ніколи не є хорошою ідеєю”.

Це не означає, що ви повинні уникати використання типів unsigned взагалі. Ні! Але якщо ви їх використовуєте, то використовуйте тільки там, де це дійсно має сенс, а також подбайте про те, щоб не допустити “змішування” типів unsigned з типами signed (як у вищенаведеному прикладі).

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

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

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

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