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

  Юрій  | 

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

 124

В уроці про цілочисельні типи даних ми говорили, що 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 Зірок (3 оцінок, середня: 5,00 з 5)
Loading...

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

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