Динамічний розподіл пам'яті в C за допомогою функцій malloc(), calloc().
Перш ніж вивчати динамічний розподіл пам’яті C, давайте розберемося:
Як працює керування пам'яттю в 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(*ptr) використовувався замість sizeof(int) щоб зробити код більш надійним, коли оголошення *ptr пізніше буде приведено до іншого типу даних.
- Розподіл може бути невдалим, якщо пам’яті недостатньо. У цьому випадку він повертає покажчик NULL. Отже, ви повинні включити код для перевірки покажчика NULL.
- Майте на увазі, що виділена пам’ять є безперервною, і її можна розглядати як масив. Ми можемо використовувати арифметику вказівника для доступу до елементів масиву замість використання дужок []. Ми радимо використовувати + для посилань на елементи масиву, оскільки використання збільшення ++ або += змінює адресу, збережену в покажчик.
Функцію Malloc() також можна використовувати з символьним типом даних, а також із складними типами даних, наприклад структурами.
функція free() у C
Пам'ять для змінні автоматично звільняється під час компіляції. У динамічному розподілі пам'яті ви повинні звільнити пам'ять явно. Якщо цього не зробити, ви можете зіткнутися з помилкою браку пам’яті.
Безкоштовний() функція викликається для звільнення/розподілу пам’яті в 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
Використовуючи C realloc () ви можете додати більший обсяг пам’яті до вже виділеної пам’яті. Він розширює поточний блок, залишаючи оригінальний вміст без змін. 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
Підсумки
- Ми можемо динамічно керувати пам’яттю, створюючи необхідні блоки пам’яті в купі
- У C Dynamic Memory Allocation пам'ять виділяється під час виконання.
- Динамічний розподіл пам'яті дозволяє маніпулювати рядками та масивами, розмір яких є гнучким і може бути змінений будь-коли у вашій програмі.
- Це потрібно, коли ви не знаєте, скільки пам'яті буде займати певна структура.
- Malloc() у C — це функція динамічного розподілу пам’яті, яка означає розподіл пам’яті, що блоки пам’яті певного розміру ініціалізуються значенням сміття
- Calloc() у C — це безперервна функція розподілу пам’яті, яка виділяє кілька блоків пам’яті одночасно, ініціалізуючи 0
- Realloc() у C використовується для перерозподілу пам’яті відповідно до вказаного розміру.
- Функція Free() використовується для очищення динамічно виділеної пам'яті.