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

Цель работы:приобрести практические навыки по динамическому выделению памяти.

Краткие теоретические сведения

Указатели чаще всего используют при работе с динамической памятью, которую иногда называют «куча» (перевод английского слова heap). Это свободная память, в которой можно во время выполнения программы выделять место в соответствии с потребностями. Доступ к выделенным участкам динамической памяти производится только через указатели. Время жизни динамических объектов – от точки создания до конца программы или до явного освобождения памяти.

Динамическая переменная хранится в некоторой области ОП, не обозначенной именем, и обращение к ней производится через переменную-указатель.

Библиотечные функции

Функции для манипулирования динамической памятью в стандарте Си следующие:

void *calloc(unsigned n, unsigned size); – выделение памяти для размещения n объек­тов размером size байт и заполнение полученной области нулями; возвращает указатель на выделенную область памяти;

void *malloc (unsigned n) – выделение области памяти для размещения бло­ка размером n байт; возвращает указатель на выделенную область памяти;

void *realloc (void *b, unsigned n) – изменение размера размещенного по адресу b блока на новое значение n и копирование (при необхо­димости) содержимого блока; возвращает указатель на перераспределенную область памяти; при возникновении ошибки, например, нехватке памяти, эти функции возвращают значение NULL, что означает отсутствие адреса (нулевой адрес);

coreleft (void) – получение размера свободной памяти в байтах только для MS DOS (используется в Borland C++), тип результата: unsigned – для моделей памяти tiny, small и medium; unsigned long – для моделей памяти compact, large и huge;

void free (void *b) – освобождение блока памяти, адресуемого указате­лем b.

Для использования этих функций требуется подключить к программе в зависимости от среды программирования заголовочный файл alloc.h или malloc.h.

Создание одномерного динамического массива

В языке Си размерность массива при объявлении должна задаваться константным выражением.

Если до выполнения программы неизвестно, сколько понадобится элементов массива, нужно использовать динамические массивы, т.е. при необходимости работы с массивами переменной размерности вместо массива достаточно объявить указатель требуемого типа и присвоить ему адрес свободной области памяти (захватить память).

Память под такие массивы выделяется с помощью функций mallос и calloc во время выполнения программы. Адрес начала массива хранится в переменной-указателе. Например:

int n = 10;

double *b = (double *) malloc(n * sizeof (double));

В примере значение переменной n задано, но может быть получено и программным путем.

Обнуления памяти при ее выделении не происходит. Инициализировать динамический массив при декларации нельзя.

Обращение к элементу динамического массива осуществляется так же, как и к элементу обычного – например а[3]. Можно обратиться к элементу массива и через косвенную адресацию – *(а + 3). В любом случае происходят те же действия, которые выполняются при обращении к элементу массива, декларированного обычным образом.

После работы захваченную под динамический массив память необходимо освободить, для нашего примера free(b);

Таким образом, время жизни динамического массива, как и любой динамической переменной – с момента выделения памяти до момента ее освобождения.

Пример работы с динамическим массивом:

#include <alloc.h>

#include<stdio.h>

void main()

{ double *x; int n;

printf("\nВведите размер массива – ");

scanf("%d", &n);

// Захват памяти

if ((x = (double*)calloc(n, sizeof(*x)))==NULL)

{ puts("Ошибка ");

return; }

...

// Работа с элементами массива

...

free(x); } // Освобождение памяти

Наши рекомендации