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

Прежде чем вы изучите распределение динамической памяти в C, давайте разберемся:

Как работает управление памятью в 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 использует кучу.

библиотека имеет функции, отвечающие за динамическое управление памятью.

Функция Цель
таНос () Выделяет память запрошенного размера и возвращает указатель на первый байт
выделенное пространство.
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. Заметить, что размер(*ptr) был использован вместо sizeof (число) чтобы сделать код более надежным, когда объявление *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 блоков памяти одинакового размера.
  • После выделения пространства памяти все байты инициализируются нулями.
  • Возвращается указатель, который в данный момент находится на первом байте выделенного пространства памяти.

Всякий раз, когда возникает ошибка при выделении памяти, например нехватка памяти, возвращается нулевой указатель.

Пример вызова():

Программа ниже вычисляет сумму арифметической последовательности.

#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 на экране:

 
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 память выделяется во время выполнения.
  • Динамическое распределение памяти позволяет манипулировать строками и массивами, размер которых является гибким и может быть изменен в любое время в вашей программе.
  • Это требуется, когда вы не знаете, сколько памяти будет занимать конкретная структура.
  • Malloc() в C — это функция динамического распределения памяти, которая означает выделение памяти, которое блокирует память определенного размера, инициализированного значением мусора.
  • Calloc() в C — это функция непрерывного выделения памяти, которая выделяет несколько блоков памяти одновременно, инициализируя их значением 0.
  • Realloc() в C используется для перераспределения памяти в соответствии с указанным размером.
  • Функция Free() используется для очистки динамически выделенной памяти.