8.1 Оперативна пам'ять
Оперативна пам'ять (RAM, ОЗП) комп'ютера представляє собою масив комірок пам'яті, кожна з яких має унікальну адресу. Ці комірки можуть зберігати дані різних типів, такі як числа, символи та вказівники. Коли програма виконується, вона розміщує свої дані та інструкції в цій пам'яті для швидкого доступу.
Приклад комірок пам'яті:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
| 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
| 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
| 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
У кожної комірки є її порядковий номер, його ще називають адресою комірки в пам'яті або просто адресою. Якщо у вашого комп'ютера 8 ГБ пам'яті, то у нього 8 мільярдів таких комірок, в яких можна зберігати щось корисне.
Біти і байти
Кожна комірка може зберігати один байт інформації. Кожен байт складається з 8 бітів, а кожен біт може містити тільки 0 або 1. Приклад (для цілих додатніх чисел):
| Число | Бітове представлення | Округлене до байта |
|---|---|---|
| 0 | 0 | 00000000 |
| 1 | 1 | 00000001 |
| 100 | 1100100 | 01100100 |
| 1000 | 1111101000 | 00000011-11101000 |
| 1000 000 000 | 111011100110101100101000000000 | 00111011-10011010-11001010-00000000 |
Чим більше байт займає змінна, тим більше значень в ній можна зберігати. Приклад:
- 1 байт — 256 унікальних значень
- 2 байти — 65 тис. унікальних значень
- 3 байти — 16 мільйонів
- 4 байти — 4 мільярди
8.2 Як дані представляються в пам'яті
Типи даних і їх представлення
Числові дані всередині процесора і в пам'яті
- Цілі числа: зберігаються в двійковій формі. Розмір може варіюватися (1 байт, 2 байти, 4 байти).
- Речові числа: зберігаються у форматі з плаваючою комою (наприклад, формат IEEE 754 для 4-байтних і 8-байтних чисел).
x = 42 # Ціле число
y = 3.14 # Речове число
Важливо! В Python вбудовані типи int і float — це повноцінні класи, які можуть реалізувати складні обчислення з числами нескінченної довжини. Проте, якщо ти будеш використовувати бібліотеки для наукових обчислень або ІІ, то зіткнешся саме з тим форматом даних, про який я розповів вище.
Символьні дані в пам'яті комп'ютера
Символи і рядки зберігаються в пам'яті у вигляді послідовностей байтів. Наприклад, в кодуванні ASCII кожен символ займає 1 байт, в кодуванні UTF-8 може займати від 1 до 4 байтів.
В Python 3.x за замовчуванням для рядків використовується кодування UTF-8, але ти можеш читати файли, де текст зберігається в інших форматах, або пересилати дані мережею не в кодуванні UTF-8.
Приклад:
char = 'A' # Символ
string = "Hello, world!" # Рядок
Окремі символи в Python не мають свого типу — для них також використовується тип str. Проте в пам'яті ці рядки зберігаються посимвольно. Один символ зазвичай займає 1—4 байти.
Вказівники
Вказівники зберігають адреси інших комірок пам'яті. Вони дозволяють програмам працювати з динамічними структурами даних і ефективніше управляти пам'яттю.
Приклад:
list = [1, 2, 3, 4] # Список
list_pointer = id(list) # Вказівник на початок списку
8.3 Приклади представлення даних в оперативній пам'яті
1. Представлення цілих чисел
Цілі числа зберігаються в пам'яті у вигляді двійкових чисел (бітів). Залежно від типу даних вони можуть займати різну кількість байтів. Наприклад, int зазвичай займає 4 байти (32 біти).
Ось так в пам'яті буде представлено число 42:
| 00000000 | 00000000 | 00000000 | 00101010 |
2. Представлення речових чисел (з плаваючою комою)
Речові числа (наприклад, тип float) зберігаються в пам'яті у форматі з плаваючою комою, зазвичай по стандарту IEEE 754. float зазвичай займає 4 байти (32 біти), а double — 8 байтів (64 біти).
Важливо! Це стандартні типи даних, прив'язаних до пам'яті і процесора. Тип float в Python відповідає загальновживаному типу double і займає 8 байт.
Ось так в пам'яті буде представлено число 3.14:
| 01000000 | 01001000 | 11110110 | 01100110 |
3. Представлення символів і рядків
Символи (наприклад, тип char) зберігаються в пам'яті у вигляді послідовності байтів. Рядки представляють собою масив символів. В мовах C/C++ рядки закінчуються нульовим байтом (\0), але в Python це не так.
Ось так в пам'яті буде представлено рядок Hello:
| 'H' | 'e' | 'l' | 'l' | 'o' |
Що в свою чергу буде представлено у вигляді 0 і 1:
| 01001000 | 01100101 | 01101100 | 01101100 | 01101111 |
8.4 Адресація динамічної пам'яті
Динамічна пам'ять виділяється і звільняється під час виконання програми, по мірі необхідності. Всі об'єкти, які ти створюєш в Python, створюються в цій пам'яті.
Вона поділяється на 2 типи:
Куча (Heap): Область пам'яті, з якої виділяються динамічні об'єкти. Управління цією пам'яттю здійснюється через функції виділення (наприклад, malloc в C) і звільнення (наприклад, free в C).
Стек (Stack): Область пам'яті, що використовується для зберігання локальних змінних і даних виклику функцій. Пам'ять автоматично виділяється і звільняється при вході і виході з функції.
Знову ж таки, я не можу привести приклад на мові Python, оскільки він занадто високорівневий для таких дій. Можу знову дати приклад на мові С:
// Динамічне виділення пам'яті для масиву з 10 цілих чисел
int *dynamic_var = (int *)malloc(sizeof(int) * 10);
// Звільнення пам'яті
free(dynamic_var);
Адресація пам'яті — це процес визначення унікальної адреси для кожної комірки пам'яті. Кожна адреса вказує на конкретне місцезнаходження в пам'яті, яке може містити дані або інструкції.
Типи адресації
Фізична адресація: прямий доступ до фізичних адрес комірок пам'яті. Управляється апаратним забезпеченням (наприклад, контролером пам'яті).
Віртуальна адресація: використовує механізм управління пам'яттю, такий як сторінкова пам'ять або сегментна пам'ять, щоб надати процесам ізольований і захищений простір адрес.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ