Динамично разпределение на паметта в C с помощта на функции malloc(), calloc().

Преди да научите C Dynamic Memory allocation, нека разберем:

Как работи управлението на паметта в C?

Когато декларирате променлива, използвайки основен тип данни, C компилаторът автоматично разпределя място в паметта за променливата в пул от памет, наречен купчина.

Например, плаваща променлива обикновено отнема 4 байта (според платформата), когато се декларира. Можем да проверим тази информация с помощта на размер на оператор, както е показано в примера по-долу

#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

Функция C malloc().

  1. Забележи това sizeof(*ptr) беше използвано вместо sizeof(int) за да направи кода по-стабилен, когато *ptr декларацията се преобразува към различен тип данни по-късно.
  2. Разпределението може да се провали, ако паметта не е достатъчна. В този случай той връща NULL указател. Така че трябва да включите код за проверка за NULL указател.
  3. Имайте предвид, че разпределената памет е непрекъсната и може да се третира като масив. Можем да използваме аритметика на указателя за достъп до елементите на масива, вместо да използваме скоби []. Съветваме ви да използвате + за препращане към елементи на масива, тъй като използването на нарастване ++ или += променя адреса, съхранен от показалка.

Функцията 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

Oбобщение

  • Можем динамично да управляваме паметта, като създаваме блокове памет според нуждите в купчината
  • В C Dynamic Memory Allocation паметта се разпределя по време на изпълнение.
  • Динамичното разпределение на паметта позволява да се манипулират низове и масиви, чийто размер е гъвкав и може да се променя по всяко време във вашата програма.
  • Изисква се, когато нямате представа колко памет ще заема дадена структура.
  • Malloc() в C е функция за динамично разпределение на паметта, която означава разпределяне на памет, която блокове памет със специфичен размер инициализира до стойност за боклук
  • Calloc() в C е функция за непрекъснато разпределение на паметта, която разпределя множество блокове памет наведнъж, инициализирано на 0
  • Realloc() в C се използва за преразпределяне на памет според определения размер.
  • Функцията Free() се използва за изчистване на динамично разпределената памет.

Обобщете тази публикация с: