logo
Подбельский Фомин_Программирование на языке СИ_

Массивы динамической памяти.

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

При традиционном определении массива:

тип имя_массива [количество_элементов];

имя_массива становится указателем на область памяти, выделяемой для размещения элементов массива. Количество_элементов в соответствии с синтаксисом языка должно быть константным выражением. Тип явно определяет размеры памяти, выделяемой для каждого элемента массива.

Таким образом, общее количество элементов массива и размеры памяти, выделяемой для него, полностью и однозначно заданы определением. Это не всегда удобно. Иногда нужно, чтобы память для массива выделялась в таких размерах, какие нужны для решения конкретной задачи, причем потребности в памяти заранее не известны и не могут быть фиксированы.

Формирование массивов с переменными размерами можно организовать с помощью указателей и средств для динамического выделения памяти. Начнем рассмотрение указанных средств с библиотечных функций, описанных в заголовочных файлах ailoc.h и stdlib.h стандартной библиотеки (файл alloc.h не является стандартным). В табл. 4.1 приведены сведения об этих библиотечных функциях. Функции malloc( ), calloc( ) и realloc( ) динамически выделяют память в соответствии со значениями параметров и возвращают адрес начала выделенного участка памяти. Для универсальности тип возвращаемого значения каждой из этих функций есть void*. Этот указатель (указатель такого типа) можно преобразовать к указателю любого типа с помощью операции явного приведения типа (тип *).

Функция free() решает обратную задачу - освобождает память, выделенную перед этим с помощью одной из трех функций calloc(), malloc( ) или realloc(). Сведения об этом участке памяти передаются в функцию free() с помощью указателя - параметра типа void *. Преобразование указателя любого типа к типу void * выполняется автоматически, поэтому вместо формального параметра void *bl можно подставить в качестве фактического параметра указатель любого типа без операции явного приведения типов.

Таблица 4.1