Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc()
Изменение длины (размера) массива, где массив это набор элементов, хранящихся в ячейках памяти расположенных одна за другой.
Как вы можете видеть на изображении выше длина (размер) массива равна 9. Но что если требуется уменьшить длину, например, с 9 до 5 элементов, чтобы не расходовать память понапрасну?
Или наоборот, если массив из 9 элементов заполнен до конца, то увеличить его, например до 12?
В этом случае используется динамическое выделение памяти (Dynamic Memory Allocation).
C располагает для этого 4 функциями, которые подключаются заголовочным файлом <stdlib.h>
и реализуют выделение памяти в С. Вот они:
Рассмотрим каждую из них подробнее:
malloc()
“malloc” или “выделение памяти” метод для динамического выделения одного большого блока памяти заданного размера.
Функция возвращает указатель типа void
, который может быть присвоен указателю (pointer) любого типа.
Синтаксис:
ptr = (cast-type*) malloc(byte-size)
Например:
ptr = (int*) malloc(5 * sizeof(int));
Т.к. размер int
равен 4-м байтам,
это выражение выделит 20 байт памяти.
Указатель ptr будет содержать
первый байт выделенной области памяти.
Если же места недостаточно, выделение завершится неудачно и будет возвращён указатель NULL.
Пример:
#include <stdio.h> #include <stdlib.h> int main() { // This pointer will hold the // base address of the block created int* ptr; int n, i, sum = 0; // Get the number of elements for the array n = 5; printf("Enter number of elements: %d\n", n); // Dynamically allocate memory using malloc() ptr = (int*)malloc(n * sizeof(int)); // Check if the memory has been successfully // allocated by malloc or not if (ptr == NULL) { printf("Memory not allocated.\n"); exit(0); } else { // Memory has been successfully allocated printf("Memory successfully allocated using malloc.\n"); // Get the elements of the array for (i = 0; i < n; ++i) { ptr[i] = i + 1; } // Print the elements of the array printf("The elements of the array are: "); for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]); } } return 0; }
Вывод программы:
Enter number of elements: 5 Memory successfully allocated using malloc. The elements of the array are: 1, 2, 3, 4, 5,
calloc()
“calloc” или “последовательное распределение” метод динамического выделения заданного кол-ва блоков указанного размера. При инициализации каждый блок получает значение по умолчанию - '0'.
Синтаксис:
ptr = (cast-type*)calloc(n, element-size);
Например:
ptr = (float*) calloc(5, sizeof(float));
Данное выражение выделяет непрерывное пространство в памяти
для 5-ти элементов, каждый из которых имеет размер 4 байта.
Если места недостаточно, возвращается указатель NULL.
Пример:
#include <stdio.h> #include <stdlib.h> int main() { // This pointer will hold the // base address of the block created int* ptr; int n, i, sum = 0; // Get the number of elements for the array n = 5; printf("Enter number of elements: %d\n", n); // Dynamically allocate memory using calloc() ptr = (int*)calloc(n, sizeof(int)); // Check if the memory has been successfully // allocated by malloc or not if (ptr == NULL) { printf("Memory not allocated.\n"); exit(0); } else { // Memory has been successfully allocated printf("Memory successfully allocated using calloc.\n"); // Get the elements of the array for (i = 0; i < n; ++i) { ptr[i] = i + 1; } // Print the elements of the array printf("The elements of the array are: "); for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]); } } return 0; }
Вывод программы:
Enter number of elements: 5 Memory successfully allocated using calloc. The elements of the array are: 1, 2, 3, 4, 5,
free()
“free” - метод используемый для освобождения (de-allocated) памяти выделенной при помощи функций malloc
и calloc
, которые сами по себе не могут освободить её. Это помогает уменьшить потери памяти.
Синтаксис:
free(ptr);
Пример:
#include <stdio.h> #include <stdlib.h> int main() { // This pointer will hold the // base address of the block created int *ptr, *ptr1; int n, i, sum = 0; // Get the number of elements for the array n = 5; printf("Enter number of elements: %d\n", n); // Dynamically allocate memory using malloc() ptr = (int*)malloc(n * sizeof(int)); // Dynamically allocate memory using calloc() ptr1 = (int*)calloc(n, sizeof(int)); // Check if the memory has been successfully // allocated by malloc or not if (ptr == NULL || ptr1 == NULL) { printf("Memory not allocated.\n"); exit(0); } else { // Memory has been successfully allocated printf("Memory successfully allocated using malloc.\n"); // Free the memory free(ptr); printf("Malloc Memory successfully freed.\n"); // Memory has been successfully allocated printf("\nMemory successfully allocated using calloc.\n"); // Free the memory free(ptr1); printf("Calloc Memory successfully freed.\n"); } return 0; }
Вывод программы:
Enter number of elements: 5 Memory successfully allocated using malloc. Malloc Memory successfully freed. Memory successfully allocated using calloc. Calloc Memory successfully freed.
realloc()
“realloc” или “перераспределение памяти” - метод позволяющий перераспределять память. Если памяти выделенной до этого при помощи функций malloc
и calloc
недостаточно, при помощи realloc
можно перераспределить её.
Синтаксис:
ptr = realloc(ptr, newSize);
где ptr это перераспределяемая область с новым размером 'newSize'.
Если же места недостаточно, указатель возвращает NULL.
Пример:
#include <stdio.h> #include <stdlib.h> int main() { // This pointer will hold the // base address of the block created int* ptr; int n, i, sum = 0; // Get the number of elements for the array n = 5; printf("Enter number of elements: %d\n", n); // Dynamically allocate memory using calloc() ptr = (int*)calloc(n, sizeof(int)); // Check if the memory has been successfully // allocated by malloc or not if (ptr == NULL) { printf("Memory not allocated.\n"); exit(0); } else { // Memory has been successfully allocated printf("Memory successfully allocated using calloc.\n"); // Get the elements of the array for (i = 0; i < n; ++i) { ptr[i] = i + 1; } // Print the elements of the array printf("The elements of the array are: "); for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]); } // Get the new size for the array n = 10; printf("\n\nEnter the new size of the array: %d\n", n); // Dynamically re-allocate memory using realloc() ptr = realloc(ptr, n * sizeof(int)); // Memory has been successfully allocated printf("Memory successfully re-allocated using realloc.\n"); // Get the new elements of the array for (i = 5; i < n; ++i) { ptr[i] = i + 1; } // Print the elements of the array printf("The elements of the array are: "); for (i = 0; i < n; ++i) { printf("%d, ", ptr[i]); } free(ptr); } return 0; }
Вывод:
Enter number of elements: 5 Memory successfully allocated using calloc. The elements of the array are: 1, 2, 3, 4, 5, Enter the new size of the array: 10 Memory successfully re-allocated using realloc. The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,