Які типи даних використовуються в С

Урок №34. Цілочисельні типи даних: short, int і long

На цьому уроці ми розглянемо цілочисельні типи даних, їх діапазони значень, а також переповнення (що це таке і приклади).

Цілочисельні типи даних

Цілочисельний тип даних — це тип, змінні якого можуть містити тільки цілі числа (без дробової частини, наприклад: -2, -1, 0, 1, 2). У мові C++ є 5 основних цілочисельних типів, доступних для використання:

Тип Мінімальний розмір
Символьний тип даних char1 байт
Цілочисельний тип даних short2 байти
int2 байти (але частіше 4 байти)
long4 байти
long long8 байт

Примітка: Тип char — це особливий випадок: він є як цілочисельним, так і символьним типом даних. Детально про це ми поговоримо на одному з наступних уроків.

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

Оголошення цілочисельних змінних

Оголошення цілочисельних змінних відбувається наступним чином:

У той час як повні назви short int , long int і long long int можуть використовуватися, їх скорочені версії (без int ) є пріоритетними для використання. До того ж постійне додавання int ускладнює читання коду (легко сплутати зі змінною).

Діапазони значень і знак цілочисельних змінних (signed і unsigned)

Як ви вже знаєте з попереднього уроку, змінна з n-ною кількістю біт може зберігати 2 n можливих значень. Але що це за значення? Це значення, які знаходяться в діапазоні. Діапазон — це значення від і до, які може зберігати певний тип даних. Діапазон цілочисельної змінної визначається двома факторами: її розміром (в бітах) і її знаком (який може бути signed або unsigned).

Цілочисельний тип signed (зі знаком) означає, що змінна може містити як додатні, так і від’ємні числа. Щоб оголосити змінну як signed, використовуйте ключове слово signed :

За замовчуванням, ключове слово signed пишеться перед типом даних.

1-байтова цілочисельна змінна зі знаком ( signed ) має діапазон значень від -128 до 127. Будь-яке значення від -128 до 127 (включно) може зберігатися в ній безпечно.

У деяких випадках ми можемо заздалегідь знати, що від’ємні числа в програмі використовуватися не будуть. Це дуже часто зустрічається при використанні змінних для зберігання кількості або розміру чого-небудь (наприклад, ваш зріст або вага не може бути від’ємною).

Цілочисельний тип unsigned (без знаку) може містити тільки додатні числа. Щоб оголосити змінну як unsigned, використовуйте ключове слово unsigned :

1-байтова цілочисельна змінна без знаку ( unsigned ) має діапазон значень від 0 до 255.

Зверніть увагу, оголошення змінної як unsigned означає, що вона не може містити від’ємні числа (тільки додатні).

Тепер, коли ви зрозуміли різницю між signed і unsigned , давайте розглянемо діапазони значень різних типів даних:

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

Для математиків: Змінна signed з n-ною кількістю біт має діапазон від -(2 n-1 ) до 2 n-1 -1. Змінна unsigned з n-ною кількістю біт має діапазон від 0 до (2 n )-1.

Для нематематиків: Використовуємо таблицю 🙂

Початківці іноді плутаються між signed і unsigned змінними. Але є простий спосіб запам’ятати їх відмінності. Чим відрізняється від’ємне число від додатного? Правильно! Мінусом спереду. Якщо мінуса немає, значить число є додатним. Отже, цілочисельний тип зі знаком ( signed ) означає, що мінус може бути присутнім, тобто числа можуть бути як додатними, так і від’ємними. Цілочисельний тип без знака ( unsigned ) означає, що мінус спереду відсутній, тобто числа можуть бути тільки додатними.

Що використовується за замовчуванням: signed чи unsigned?

Так що ж станеться, якщо ми оголосимо змінну без вказівки signed чи unsigned ?

Тип За замовчуванням
Символьний тип даних charsigned або unsigned (найчастіше signed)
Цілочисельний тип даних shortsigned
intsigned
longsigned
long longsigned

Всі цілочисельні типи даних, крім char, є signed за замовчуванням. Тип char може бути як signed , так і unsigned (але найчастіше signed ).

У більшості випадків ключове слово signed не пишеться (воно і так використовується за замовчуванням), за винятком типу char (тут краще уточнити).

Програмісти, як правило, уникають використання цілочисельних типів unsigned , якщо в цьому немає особливої потреби, так як зі змінними unsigned помилок, за статистикою, виникає більше, ніж зі змінними signed .

Правило: Використовуйте цілочисельні типи signed, замість unsigned.

Переповнення

Питання: “Що станеться, якщо ми спробуємо використовувати значення поза діапазону допустимих значень?”. Відповідь: “Переповнення”.

Переповнення (англ. “overflow”) трапляється при втраті біт через те, що змінній не було виділено достатньо пам’яті для їх зберігання.

На уроці №31 ми говорили про те, що дані зберігаються в бінарному (двійковому) форматі і кожен біт може мати тільки 2 можливих значення ( 0 або 1 ). Ось як виглядає діапазон чисел від 0 до 15 в десятковій та двійковій системах:

Десяткова система Двійкова система
00
11
210
311
4100
5101
6110
7111
81000
91001
101010
111011
121100
131101
141110
151111

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

Приклади переповнення

Розглянемо змінну unsigned , яка складається з 4 біт. Будь-яке з двійкових чисел, перерахованих в таблиці вище, поміститься усередині цієї змінної.

Але що станеться, якщо ми спробуємо присвоїти значення, яке займає більше 4 біт? Правильно! Переповнення. Наша змінна зберігатиме тільки 4 найменш значущих (ті, що праворуч) біти, а всі інші біти — загубляться.

Наприклад, якщо ми спробуємо помістити число 21 в нашу 4-бітну змінну:

Число 21 займає 5 біт (10101). 4 біти справа (0101) помістяться в змінну, а крайній лівий біт (1) просто загубиться. Тобто наша змінна міститиме 0101, що дорівнює 101 (нуль спереду не рахується), а це вже число 5, а не 21.

Тепер давайте розглянемо приклад на практиці (тип short займає 16 біт):

Основні (базові) типи даних C++

В C++ реалізовано такі основні цілочисельні типи даних:

short int unsigned short int int unsigned int long (long int) unsigned long (unsigned long int) long long unsigned long long

Ці типи даних представляють значення з множини цілих чисел. Наприклад:

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

Дані типу short int , unsigned short int займають у два рази менше місця в пам’яті ніж дані типу int , unsigned int . У нових версіях компілятора дані типу short int займають 2 байти.

У старіших версіях компіляторів дані типу long , unsigned long займають у два рази більше місця в пам’яті ніж дані типу int , unsigned int . В останніх версіях компіляторів дані типу int ( unsigned int ) займають таке саме місце в оперативній пам’яті як і дані типу long ( unsigned long ).

Дані типу long long ( unsigned long long ) займають у 2 рази більше місця в пам’яті ніж дані типу long ( unsigned long ).

Приклад. У прикладі визначається розмір даних цілочисельного типу з допомогою інструкції sizeof . Більш детально про оператор sizeof можна прочитати тут .

#include using namespace std; void main() < // Розмір в байтах різних цілочисельних типів cout “sizeof(short int) color: #0000ff;”>sizeof(short int) << endl; cout "sizeof(unsigned short int) color: #0000ff;">sizeof(unsigned short int) << endl; cout "sizeof(int) color: #0000ff;">sizeof(int) << endl; cout "sizeof(unsigned int) color: #0000ff;">sizeof(unsigned int) << endl; cout "sizeof(long) color: #0000ff;">sizeof(long) << endl; cout "sizeof(unsigned long) color: #0000ff;">sizeof(unsigned long) << endl; cout "sizeof(long long) color: #0000ff;">sizeof(long long) << endl; cout "sizeof(unsigned long long) color: #0000ff;">sizeof(unsigned long long)

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

sizeof(short int) = 2 sizeof(unsigned short int) = 2 sizeof(int) = 4 sizeof(unsigned int) = 4 sizeof(long) = 4 sizeof(unsigned long) = 4 sizeof(long long) = 8 sizeof(unsigned long long) = 8

Проаналізувавши результат, можна прийти до висновку, що в нових версіях компіляторів:

  • змінні типів short int та unsigned short int займають 2 байти;
  • змінні типів int , unsigned int , long ( long int ), unsigned long ( unsigned long int ) займають 4 байти;
  • змінні типів long long ( unsigned long long ) займають 8 байт.

3. Як у програмі описати змінну з іменем x цілого типу?

int x; // ціле зі знаком

У результаті під змінну x буде виділене місце в пам’яті розміром 4 байти. Розмір пам’яті, що виділяється під змінну залежить від характеристик комп’ютера, типу операційної системи та налаштувань компілятора.

4. Як у змінну цілого типу записати число 239?

Для цього використовується оператор присвоєння, який позначається символом ‘ = ‘.

Відповідь 1. Внесення числа у змінну після її опису.

int x; x = 239;

Відповідь 2. Внесення числа у змінну під час її опису (початкова ініціалізація).

5. Які особливості типів даних з плаваючою комою?

Типи даних з плаваючою комою дозволяють представляти значення з множини дійсних чисел. Наприклад:

8.35 -990.399 239.0

У C++ є такі основні типи даних з плаваючою комою: float , double , long double .

Змінна типу double займає в 2 рази більше місця в пам’яті комп’ютера ніж змінна типу float .

Так само змінна типу long double займає в 2 рази більше місця в пам’яті комп’ютера, ніж змінна типу double .

6. Як описати змінну, яка приймає значення з плаваючою комою?

Приклад опису змінних типу float , double , long double :

float f; double d; long double ld;

7. Як в змінну з плаваючою комою записати числові значення?

Приклад внесення числових даних в змінні типів з плаваючою комою:

float f = -9928.45; // початкова ініціалізація double d; long double ld; d = 0.445332; // оператор присвоєння ld = 3892923898239.030903; // оператор присвоєння

8. Як перевести змінну типу float в тип int ?

Для цього використовується операція приведення типів. У дужках потрібно вказати назву типу до якого відбувається приведення.

float a; int b; a = 8.457; b = (int) a; // b = 8

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

Наприклад, змінна типу short int може представляти менший діапазон чисел, ніж змінні типу float , double . У наступному лістингу відбувається переповнення значення у змінній типу short int :

short int i; float f; f = 3990099.8; i = (int)f; // i = -7597 - переповнення

9. Як перевести змінну з типу int в тип double ?

Приклад приведення з int в double :

int i; double d; i = 982; d = (double)i; // d = 982.0

10. Які особливості використання даних типу char (символьних даних) у програмі?

Дані типу char представляють символьне значення коду, введеного з клавіатури. Код символу представляє собою ціле число.

Наприклад, код символу ‘f’ рівний значенню 102 .

Фрагмент коду, в якому обчислюється код символу:

int code; char symbol; symbol = 'f'; code = (int)symbol; // code = 102

Тобто, дані типу char є тими самими цілими числами. Дані типу char займають в пам’яті комп’ютера 1 байт.

Співвідношення “символ-код” розміщується у таблиці символів Windows. Символи з кодами від 0 до 127 – це зарезервовані символи BIOS. Вони включають найбільш вживані символи, символи цифр, символи латинської абетки. Ці символи змінити неможна.

Символи з кодами від 128 до 255 – це регіональні символи, що прив’язані до конкретної абетки того комп’ютера на якому встановлена операційна система Windows.

11. Які особливості використання даних типу bool (логічний тип)?

Змінні типу bool можуть приймати тільки два значення:

Ці змінні використовуються для перевірки логічних виразів. Числове значення true рівне 1 . Числове значення false рівне 0 .

Фрагмент коду, що визначає числові значення true та false :

int result; bool b; result = (int)true; // result = 1 b = false; result = (int)b; // result = 0

Фрагмент коду, що перетворює типи int та float в bool :

int i; float f; bool b; i = 6; b = (bool)i; // b = True f = 0.0; b = (bool)f; // b = False

12. Як визначити розмір того чи іншого типу в C ++ ?

Для цього використовується операція sizeof() .

Фрагмент коду, що визначає розмір деяких типів даних:

int d; d = sizeof(char); // d = 1 d = sizeof(unsigned int); // d = 4 d = sizeof(float); // d = 4 d = sizeof(double); // d = 8

13. Яким чином здійснюється ініціалізація змінних різних типів?

int d = 28; float z = (float)2.85; char c = 'k'; String ^s = "Hello!"; double r = -8.559;

14. Яким чином визначити максимально допустиме (мінімально допустиме) значення змінної певного типу?

Щоб визначити максимально допустиме чи мінімально допустиме значення змінної деякого типу в бібліотеці .NET Framework використовуються властивості MaxValue та MinValue .

Приклади визначення граничних значень змінних різних типів.

// тип int int i; long MaxInt; long MinInt; MaxInt = (long)i.MaxValue; // MaxInt = 2147483647 MinInt = (long)i.MinValue; // MinInt = -2147483648

Для змінних типу short int :

// тип short int short int si; int MaxInt; int MinInt; MaxInt = (int)si.MaxValue; // MaxInt = 32767 MinInt = (int)si.MinValue; // MinInt = -32768

Для змінних типу unsigned int :

// тип unsigned int unsigned int ui; unsigned int MaxInt; unsigned int MinInt; MaxInt = ui.MaxValue; // MaxInt = 4294967295 MinInt = ui.MinValue; // MinInt = 0
// тип float float f; float MaxF; float MinF; MaxF = f.MaxValue; // MaxF = 3.402823E+38 MinF = f.MinValue; // MinF = -3.402823E+38
// тип double double d; double MaxD; double MinD; MaxD = d.MaxValue; // MaxD = 1.79769313486232E+308 MinD = d.MinValue; // MinD = -1.79769313486232E+308
// тип char char c; int MaxC; int MinC; MaxC = (int)c.MaxValue; // MaxC = 127 MinC = (int)c.MinValue; // MinC = -128

15. Які особливості використання типу enum ?

Тип enum – це перечислювальний тип даних. В ньому задаються мнемонічні значення для множин цілих значень. Кожне мнемонічне значення має певний зміст і позначається цілим числом.

Приклад використання типу enum для позначення місяців року:

enum months < January, February, March, April, May, June, July, August, September, October, November, December > mn; mn = January; // mn = 0 mn = March; // mn = 2 mn = September; // mn = 8

У наведеному прикладі описується змінна з іменем mn типу enum months . Мнемонічні значення місяців ( January , February , …) починаються з 0 ( 0 , 1 , 2 , …). Мнемонічному значенню January відповідає ціле значення 0 , мнемонічному значенню February відповідає ціле значення 1 , і т.д.

Отже, завдяки типу enum , у тексті програми можна використовувати мнемонічні позначення для кращої наочності вихідного коду.

mn = (enum months)2; // mn = March mn = (enum months)11; // mn = December

16. Які особливості застосування типу void в програмах на C++ ? Покажчик на void

Тип даних void використовується у наступних випадках:

  • коли потрібно описати функцію, яка не повертає ніякого значення (див. приклад);
  • коли потрібно описати функцію, яка не отримує параметрів (див. приклад);
  • якщо потрібно оголосити покажчик на void , який може взаємодіяти з покажчиками на інші типи (дивіться приклад нижче). У даному випадку, покажчик на void може бути приведений до типу покажчика на будь-який інший тип ( int* , float* , double* і т.д.)

Приклад 1. Функція MyFun() без параметрів, яка не повертає ніякого значення (повертає тип void ) і не отримує параметрів.

public: void MyFun(void) < // тіло функції // . return; // повернення з функції, яка не повертає значення > // виклик функції з програми . MyFun(); .

Приклад 2. У прикладі демонструються деякі особливості використання покажчика на void .

#include using namespace std; void main() < // Оголосити покажчик на void void *pVoid; // Оголосити покажчики на інші типи int *pInt = new int; float *pFloat = new float; char *pChar = new char; double *pDouble = new double; // Заповнити значення за покажчиками на інші типи *pInt = 25; *pFloat = (float)3.88; *pChar = '+'; *pDouble = 17.25; // Присвоїти покажчику на void значення покажчиків на інші типи // - на покажчик на тип float pVoid = pFloat; // покажчик pVoid вказує на область пам'яті pFloat *(float*)pVoid = 85.77; // змінити значення *pFloat cout "*pFloat color: #008000;">// *pFloat = 85.77 // - на покажчик типу char* pVoid = pChar; *(char*)pVoid = 'a'; cout "*pChar color: #008000;">// *pChar = a // ----------------------------------------------------------------- // Використати покажчик на void для обміну значеннями покажчиків на int int *p1 = new int; int *p2 = new int; // заповнити значеннями пам'ять, на яку вказують покажчики p1, p2 *p1 = 28; *p2 = 35; cout "*p1 color: #008000;">// *p1 = 28 cout "*p2 color: #008000;">// *p2 = 35 // обмін значеннями покажчиків з допомогою покажчика на void pVoid = p1; p1 = p2; p2 = (int*)pVoid; cout "*p1 color: #008000;">// *p1 = 35 cout "*p2 color: #008000;">// *p2 = 28 >

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

*pFloat = 85.77 *pChar = a *p1 = 28 *p2 = 35 *p1 = 35 *p2 = 28

17. Чи можна оголошувати змінну типу void в програмі?

Не можна, Тому що тип void не зв’язаний зі значенням. Оголошення змінної типу void призводить до помилки компіляції з повідомленням:

"Illegal use of type void".

Однак, можна оголосити покажчик на void .

18. Які особливості застосування типу wchar_t у Visual C++?

Змінні типу char (дивіться попередні пункти) використовуються для зберігання 8-розрядних ASCII -символів.

Тип wchar_t використовується для зберігання символів, що входять у склад великих символьних наборів. Наприклад, у китайській абетці є величезна кількість символів. 8 розрядів є недостатньо, щоб представити увесь набір символів китайської абетки. Тому, якщо потрібно використовувати програму на міжнародному ринку, доцільно замінити тип char на wchar_t .

Приклад використання типу wchar_t .

. wchar_t t; // для змінної t виділяється 2 байти пам'яті t = 's'; . 

19. Який об’єм пам’яті резервується для опису однієї змінної типу wchar_t ?

Одна змінна типу wchar_t займає в пам’яті комп’ютера 2 байти (16 біт). Діапазон цілочисельних значень змінних типу wchar_t становить від 0 до 65535.

20. Як визначити, яке максимальне (мінімальне) значення може містити змінна цілочисельного або символьного типу? Константи INT32_MIN , INT32_MAX та інші

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

Наприклад, якщо змінна цілого типу займає 2 байти (16 біт), то діапазон допустимих значень може бути таким:

  • для знакових змінних: -32768 … 32767;
  • для беззнакових змінних (з приставкою unsigned ): 0 … 65535.

В C++ є засоби для визначення мінімального та максимального значення, яке може приймати змінна цілочисельного або символьного типу. У бібліотеку C++ входить модуль , який містить опис відповідних констант. Ці константи можна використовувати у програмах при перехопленні різноманітних виключних ситуацій, наприклад, переповнення, вихід за межі індексу в масиві тощо.

Наприклад, щоб порівняти значення змінної типу int на максимальне, можна використати константу INT32_MAX за зразком, як показано нижче

. // Визначення моменту, коли відбувається переповнення int i = 0; while (1) < // збільшити лічильник i++; // деякі операції // . // порівняти на максимально-допустиме значення if (i == INT32_MAX) < cout "Error. Overflow."; return; > > .

Приклад. Нижченаведений приклад демонструє використання обмежувальних констант для символьних та цілочисельних типів.

#include using namespace std; void main() < // Символьні типи даних - максимальні та мінімальні значення cout "SCHAR_MIN color: #800080;">SCHAR_MIN // char - мінімальне значення cout "SCHAR_MAX color: #800080;">SCHAR_MAX // char - максимальне значення cout "USCHAR_MAX color: #800080;">UCHAR_MAX // unsigned char - максимум // Цілочисельні типи даних - максимальні та мінімальні значення cout "SHRT_MIN color: #800080;">SHRT_MIN // short int - мінімальне значення cout "SHRT_MAX color: #800080;">SHRT_MAX // short int - максимальне значення cout "USHRT_MAX color: #800080;">USHRT_MAX // unsigned short int - максимум cout "INT16_MAX color: #800080;">INT16_MAX // int (16 розрядне) - мінімум cout "INT16_MIN color: #800080;">INT16_MIN // int (16 розрядне) - максимум cout "UINT16_MAX color: #800080;">UINT16_MAX // unsigned int - максимум cout "INT32_MIN color: #800080;">INT32_MIN // int (32-розрядне) - мінімум cout "INT32_MAX color: #800080;">INT32_MAX // int (32-розрядне) - максимум cout "UINT32_MAX color: #800080;">UINT32_MAX // unsigned int - максимум cout "LONG_MIN color: #800080;">LONG_MIN // long int - мінімум cout "LONG_MAX color: #800080;">LONG_MAX // long int - максимум cout "ULONG_MAX color: #800080;">ULONG_MAX // unsigned long - максимум cout "LLONG_MAX color: #800080;">LLONG_MAX // long long - максимум cout "LLONG_MIN color: #800080;">LLONG_MIN // long long - мінімум cout "ULLONG_MAX color: #800080;">ULLONG_MAX // unsigned long long - максимум >

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

SCHAR_MIN = -128 SCHAR_MAX = 127 USCHAR_MAX = 255 SHRT_MIN = -32768 SHRT_MAX = 32767 USHRT_MAX = 65535 INT16_MAX = 32767 INT16_MIN = -32768 UINT16_MAX = 65535 INT32_MIN = -2147483648 INT32_MAX = 2147483647 UINT32_MAX = 4294967295 LONG_MIN = -2147483648 LONG_MAX = 2147483647 ULONG_MAX = 4294967295 LLONG_MAX = 9223372036854775807 LLONG_MIN = -9223372036854775808 ULLONG_MAX = 18446744073709551615

Зв’язані теми