Динамічне виділення пам'яті в C: malloc(), calloc()
⚡ Розумний підсумок
Динамічне виділення пам'яті в C резервує та звільняє пам'ять купи під час виконання за допомогою функцій malloc(), calloc(), realloc() та free() з бібліотеки stdlib.h, дозволяючи програмам гнучко визначати розмір масивів та структур, коли вимоги невідомі до виконання.

Як працює керування пам'яттю в C?
Коли ви оголошуєте змінну з використанням базового типу даних, компілятор C автоматично виділяє місце пам'яті для змінної в пулі пам'яті, який називається стеком.
Наприклад, змінна типу "float" зазвичай займає 4 байти (залежно від платформи) під час оголошення. Ми можемо перевірити цю інформацію за допомогою оператора sizeof, як показано в прикладі нижче.
#include <stdio.h> int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}
Вихідний сигнал буде:
The size of float is 4 bytes
Крім того, масив із заданим розміром виділяється в суміжні блоки пам'яті, кожен блок має розмір для одного елемента:
#include <stdio.h> int main() { float arr[10]; printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}
Результат:
The size of the float array with 10 element is 40
Як було з'ясовано досі, під час оголошення базового типу даних або масиву пам'ять керується автоматично. Однак існує процес виділення пам'яті в мові C, який дозволяє реалізувати програму, в якій розмір масиву не визначений до запуску програми (середовище виконання). Цей процес називається «динамічним виділенням пам'яті».
Динамічний розподіл пам'яті в C
Динамічне виділення пам'яті — це ручне виділення та звільнення пам'яті відповідно до потреб вашого програмування. Динамічна пам'ять керується та обслуговується за допомогою вказівників, які вказують на щойно виділений простір пам'яті в області, яку ми називаємо купою.
Тепер ви можете без проблем створювати та знищувати масив елементів динамічно під час виконання. Підсумовуючи, автоматичне керування пам’яттю використовує стек, а C Dynamic Memory Allocation – купу.
The Бібліотека має функції, що відповідають за динамічне керування пам'яттю.
| функція | Мета |
|---|---|
| malloc () | Виділяє пам'ять необхідного розміру та повертає вказівник на перший байт виділений простір. |
| calloc() | Виділяє простір для елементів масиву. Ініціалізує елементи нулем і повертає покажчик на пам’ять. |
| realloc () | Він використовується для зміни розміру раніше виділеного простору пам'яті. |
| безкоштовно() | Звільняє або очищає раніше виділений простір пам’яті. |
Давайте обговоримо наведені вище функції з їх застосуванням
функція malloc() у C
Функція C malloc() означає розподіл пам’яті. Це функція, яка використовується для динамічного виділення блоку пам'яті. Він резервує простір пам’яті заданого розміру та повертає нульовий покажчик, що вказує на розташування пам’яті. Зазвичай повертається вказівник типу void. Це означає, що ми можемо призначити C malloc() будь-якому покажчику.
Синтаксис функції malloc():
ptr = (cast_type *) malloc (byte_size);
Тут,
- ptr є вказівником на cast_type.
- Функція C malloc() повертає вказівник на виділену пам’ять byte_size.
Приклад malloc():
Example: ptr = (int *) malloc (50)
Коли цей оператор успішно виконується, резервується простір пам’яті розміром 50 байт. Адреса першого байта зарезервованого простору присвоюється покажчику ptr типу int.
Розглянемо інший приклад:
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
вихід:
Value of the 6th integer is 480
- Зверніть увагу, що замість sizeof(int) було використано sizeof(*ptr), щоб зробити код більш стійким, коли оголошення *ptr пізніше буде перетворено на інший тип даних.
- Розподіл може бути невдалим, якщо пам’яті недостатньо. У цьому випадку він повертає покажчик NULL. Отже, ви повинні включити код для перевірки покажчика NULL.
- Майте на увазі, що виділена пам’ять є безперервною, і її можна розглядати як масив. Ми можемо використовувати арифметику вказівника для доступу до елементів масиву замість використання дужок []. Ми радимо використовувати + для посилань на елементи масиву, оскільки використання збільшення ++ або += змінює адресу, збережену в покажчик.
Функцію Malloc() також можна використовувати з символьним типом даних, а також із складними типами даних, наприклад структурами.
функція free() у C
Пам'ять для змінні автоматично звільняється під час компіляції. У динамічному розподілі пам'яті ви повинні звільнити пам'ять явно. Якщо цього не зробити, ви можете зіткнутися з помилкою браку пам’яті.
Функція free() викликається для звільнення/розподілу пам'яті в C. Звільняючи пам'ять у вашій програмі, ви робите більше доступної для використання пізніше.
Наприклад:
#include <stdio.h> int main() { int* ptr = malloc(10 * sizeof(*ptr)); if (ptr != NULL){ *(ptr + 2) = 50; printf("Value of the 2nd integer is %d",*(ptr + 2)); } free(ptr); }
вихід:
Value of the 2nd integer is 50
функція calloc() у C
Функція C calloc() означає безперервний розподіл. Ця функція використовується для виділення кількох блоків пам'яті. Це функція динамічного розподілу пам’яті, яка використовується для виділення пам’яті складним структурам даних, таким як масиви та структури.
Функція Malloc() використовується для виділення одного блоку пам’яті, тоді як calloc() у C використовується для виділення кількох блоків пам’яті. Кожен блок, виділений функцією calloc(), має однаковий розмір.
Синтаксис функції calloc():
ptr = (cast_type *) calloc (n, size);
Наведений вище оператор використовується для виділення n блоків пам’яті однакового розміру.
Після виділення простору пам'яті всі байти ініціалізуються нулем.
Повертається покажчик, який зараз знаходиться на першому байті виділеного простору пам’яті.
Щоразу, коли виникає помилка виділення простору пам’яті, наприклад нестача пам’яті, повертається нульовий покажчик.
Приклад calloc():
Наведена нижче програма обчислює суму арифметичної послідовності.
#include <stdio.h> int main() { int i, * ptr, sum = 0; ptr = calloc(10, sizeof(int)); if (ptr == NULL) { printf("Error! memory not allocated."); exit(0); } printf("Building and calculating the sequence sum of the first 10 terms \ n "); for (i = 0; i < 10; ++i) { * (ptr + i) = i; sum += * (ptr + i); } printf("Sum = %d", sum); free(ptr); return 0; }
Результат:
Building and calculating the sequence sum of the first 10 terms
Sum = 45
calloc() проти malloc(): ключові відмінності
Нижче наведено ключову відмінність між malloc() проти calloc() в C:
Функція calloc() загалом більш придатна та ефективна, ніж функція malloc(). Хоча обидві функції використовуються для виділення простору пам’яті, calloc() може виділяти декілька блоків одночасно. Вам не потрібно кожного разу запитувати блок пам'яті. Функція calloc() використовується у складних структурах даних, які потребують більшого простору пам’яті.
Блок пам’яті, виділений calloc() у C, завжди ініціалізується рівним нулю, тоді як у функції malloc() у C він завжди містить сміттєве значення.
функція realloc() у C
Використовуючи функцію realloc() у C, ви можете збільшити обсяг пам'яті до вже виділеної пам'яті. Вона розширює поточний блок, залишаючи початковий вміст незмінним. realloc() у C означає перерозподіл пам'яті.
realloc() також можна використовувати для зменшення розміру раніше виділеної пам’яті.
Синтаксис функції realloc():
ptr = realloc (ptr,newsize);
Наведений вище оператор виділяє новий простір пам’яті із заданим розміром у змінній newsize. Після виконання функції вказівник буде повернено на перший байт блоку пам'яті. Новий розмір може бути більшим або меншим за попередню пам’ять. Ми не можемо бути впевнені, що щойно виділений блок буде вказувати на те саме розташування, що й попередній блок пам’яті. Ця функція скопіює всі попередні дані в новий регіон. Це гарантує безпеку даних.
Приклад realloc():
#include <stdio.h> int main () { char *ptr; ptr = (char *) malloc(10); strcpy(ptr, "Programming"); printf(" %s, Address = %u\n", ptr, ptr); ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size strcat(ptr, " In 'C'"); printf(" %s, Address = %u\n", ptr, ptr); free(ptr); return 0; }
Щоразу, коли realloc() у C призводить до невдалої операції, він повертає нульовий покажчик, і попередні дані також звільняються.
Динамічні масиви в C
Динамічний масив у C дозволяє збільшувати кількість елементів за потреби. C Динамічний масив широко використовується в алгоритмах інформатики.
У наступній програмі ми створили та змінили розмір динамічного масиву C
#include <stdio.h> int main() { int * arr_dynamic = NULL; int elements = 2, i; arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks for (i = 0; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); elements = 4; arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements printf("After realloc\n"); for (i = 2; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); free(arr_dynamic); }
Результат програми C Dynamic array на екрані:
arr_dynamic[0]=0 arr_dynamic[1]=1 After realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3

