Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Динамическое выделение памяти в C: освоение malloc, calloc, realloc и free

Динамическое выделение памяти в C

Это руководство проведет вас через динамическое выделение памяти в C с использованием стандартных функций библиотеки malloc(), calloc(), realloc() и free(), с понятными примерами и лучшими практиками.

Зачем использовать динамическое выделение?

Статические массивы имеют фиксированный размер, объявленный во время компиляции, что может привести к нерациональному расходу памяти или недостаточной емкости во время выполнения. Динамическое выделение позволяет запрашивать ровно столько памяти, сколько нужно, пока программа работает.

Все четыре функции определены в заголовочном файле <stdlib.h> и предоставляют контролируемый способ управления памятью кучи.


malloc() — выделение блока байтов

Название malloc расшифровывается как «memory allocation». Она резервирует непрерывный блок памяти указанного размера (в байтах) и возвращает указатель типа void *, который можно привести к любому другому типу указателя.

Синтаксис

ptr = malloc(size_in_bytes); // приведение к нужному типу при необходимости

Пример

float *ptr = malloc(100 * sizeof(float)); // 400 байт на большинстве систем

Здесь ptr указывает на первый байт блока в 400 байт. Если запрос не удается, malloc возвращает NULL. Рекомендуется избегать ненужных приведений в C; компилятор может вывести тип при присваивании результата типизированному указателю.


calloc() — выделение и обнуление

calloc означает «contiguous allocation». В отличие от malloc, она инициализирует каждый бит выделенного блока нулями, что делает ее безопасной для числовых типов и указателей.

Синтаксис

ptr = calloc(num_elements, size_of_each_element);

Пример

float *ptr = calloc(25, sizeof(float)); // 25 обнуленных элементов float

Возвращаемый указатель равен NULL, если выделение не удалось.


free() — освобождение выделенной памяти

Память, полученная с помощью malloc или calloc, сохраняется до явного освобождения. free() деаллоцирует блок и возвращает память в кучу для повторного использования.

Синтаксис

free(ptr);

Вызов free для NULL указателя безопасен и ничего не делает.


Пример 1: Использование malloc() и free()

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int n, i, *ptr, sum = 0;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    ptr = malloc(n * sizeof(int));
    if (!ptr) {
        fprintf(stderr, "Error: memory not allocated.\n");
        return EXIT_FAILURE;
    }
    printf("Enter elements: ");
    for (i = 0; i < n; ++i) {
        scanf("%d", ptr + i);
        sum += *(ptr + i);
    }
    printf("Sum = %d\n", sum);
    free(ptr);
    return EXIT_SUCCESS;
}

Вывод

Enter number of elements: 3
Enter elements: 100 20 36
Sum = 156

Пример 2: Использование calloc() и free()

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int n, i, *ptr, sum = 0;
    printf("Enter number of elements: ");
    scanf("%d", &n);
    ptr = calloc(n, sizeof(int));
    if (!ptr) {
        fprintf(stderr, "Error: memory not allocated.\n");
        return EXIT_FAILURE;
    }
    printf("Enter elements: ");
    for (i = 0; i < n; ++i) {
        scanf("%d", ptr + i);
        sum += *(ptr + i);
    }
    printf("Sum = %d\n", sum);
    free(ptr);
    return EXIT_SUCCESS;
}

Вывод

Enter number of elements: 3
Enter elements: 100 20 36
Sum = 156

realloc() — изменение размера существующего выделения

Если вы обнаружите, что текущее выделение слишком мало или больше необходимого, realloc() корректирует размер, сохраняя существующие данные (до нового размера).

Синтаксис

ptr = realloc(ptr, new_size_in_bytes);

Она возвращает указатель на перераспределенный блок или NULL при неудаче. Чтобы избежать утечек памяти, сохраняйте результат во временном указателе.

Пример 3: Использование realloc()

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int *ptr, i, n1, n2;
    printf("Enter initial size: ");
    scanf("%d", &n1);
    ptr = malloc(n1 * sizeof(int));
    if (!ptr) {
        fprintf(stderr, "Allocation failed.\n");
        return EXIT_FAILURE;
    }
    printf("Addresses before reallocation:\n");
    for (i = 0; i < n1; ++i) printf("%p\n", ptr + i);
    printf("\nEnter new size: ");
    scanf("%d", &n2);
    int *tmp = realloc(ptr, n2 * sizeof(int));
    if (!tmp) {
        fprintf(stderr, "Reallocation failed.\n");
        free(ptr);
        return EXIT_FAILURE;
    }
    ptr = tmp;
    printf("Addresses after reallocation:\n");
    for (i = 0; i < n2; ++i) printf("%p\n", ptr + i);
    free(ptr);
    return EXIT_SUCCESS;
}

Типичный вывод

Enter initial size: 2
Addresses before reallocation:
0x7ffc12345670
0x7ffc12345674
Enter new size: 4
Addresses after reallocation:
0x7ffc12345670
0x7ffc12345674
0x7ffc12345678
0x7ffc1234567c

Освоив эти четыре функции и применяя правильную обработку ошибок, вы сможете безопасно и эффективно управлять памятью кучи в любом приложении на C.

Язык C

  1. Понимание ROM, PROM, EPROM и EEPROM: дизайн, программирование и идентификация
  2. Микропроцессоры: эволюция вычислений с запрограммированной памятью
  3. Управление памятью в C++: экспертное использование new и delete
  4. Cervoz представляет DDR4-2666 для промышленных AI и IoT решений
  5. Динамическое выделение массивов в C++: практическое руководство с примерами кода
  6. calloc() в C: выделение обнулённой памяти и практический пример
  7. Использование realloc() в C: синтаксис, лучшие практики и пример
  8. Динамическое управление памятью в C: malloc, calloc, realloc, free
  9. Динамическое ценообразование возвращается в традиционный ритейл: почему это неизбежно
  10. Динамическая память в C++: стек против кучи