Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
30
Добавлен:
13.03.2016
Размер:
56.32 Кб
Скачать

Понятие о динамических данных. Динамические массивы.

лекция №17

Данные, используемые паскаль-программой

Статические

(глобальные):

•описываются в разделах (переменных и констант) программы;

•распределяются в памяти на этапе компиляции и существуют все время выполнения программы;

•место в памяти – статический сегмент;

•доступны в любой точке программы, за исключением подпрограмм, имеющих локальные переменные с тем же именем.

Локальные:

•описываются в разделах (переменных и констант) подпрограммы;

•распределяются в памяти на этапе выполнения (при каждом вызове подпрограммы) и освобождают память при завершении работы программы;

•место в памяти – стэк;

•доступны в блоке подпрограммы.

Динамические:

•описываются не данные, а их адреса (указатели);

•распределяются и уничтожаются в памяти на этапе выполнения программы по специальным командам;

•место в памяти –

динамическая память (англ. куча – heap);

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

Динамическое распределение памяти используется:

когда статической памяти и стека подпрограмм не хватает для решения задачи;

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

Что такое указатель?

• Указатель - абстрактное обобщение адреса.

Указатель не определяют как переменную, принимающую значения на множестве адресов, потому что значение адреса зависит от конкретной ЭВМ и условий, в которых происходит работа компилятора.

Указатели используются при работе с динамической памятью.

Тип указатель имеется во всех универсальных языках программирования.

Указатели в Объектном Паскале

Типированные

 

Нетипированные

Описание типированного указателя:

VAR имя_типированного_указателя: ^тип_содержимого_ячейки;

В качестве типа содержимого ячейки (базового типа) может быть использован любой стандартный тип или имя нестандартного типа.

Описание нетипированного указателя:

имя_нетипированного_указателя: pointer;

Операция @ - взятие адреса переменной;

@A – адрес переменной A (или адрес первого байта массива или

структуры A).

Операция ^ - взятие содержимого;

b ^ – содержимое ячейки с адресом b (сравните положение значка ^ с тем, что используется при объявлении указателей).

b ^ можно использовать точно так же, как и переменную базового для указателя b типа.

Указатели в Объектном Паскале (продолжение)

Статический сегмент памяти

Пример.

 

С

 

Var C: ^integer; i:integer;

 

Begin C:=@i; {в ячейку С записан

 

 

адрес ячейки i}

 

 

C^:=1; {в ячейку с

 

 

адресом С записано значение 1}

 

i

 

 

 

End.

 

 

 

 

 

C:=@i {после этого оператора i ^C}

C^:=1эквивалентно i:=1

Встроенная константа nil - пустой или нулевой указатель. Значение nil означает, что указатель не хранит значения адреса какой-либо ячейки памяти.

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

Операторы (процедуры) для распределения

иосвобождения памяти

Процедура new(p), где p – типированный указатель, выделяет область памяти, на которую указывает (т. е. адрес которой хранит) р. При этом p^ представляет собой переменную базового для р типа и называется динамической переменной.

Процедура dispose(p) возвращает выделенную с помощью new(p) память

вкучу. После применения dispose(p) значение указателя р становится неопределенным (не становится равным nil!). Применение dispose к пустому указателю вызывает сообщение об ошибке.

Процедура GetMem(p,n) выделяет область динамической памяти из n байтов, на которую указывает р – типированный или нетипированный указатель.

Функция AllocMem(p) возвращает значение нетипированного указателя на область из n байтов;

в отличии от GetMem, AllocMem заполняет выделенную область нулями.

Процедура FreeMem(p) освобождает память, полученную с помощью

GetMem или AllocMem.

Мы будем работать только с специальным видом динамических переменных – динамическими массивами!

Почему неудобны статические (или локальные) массивы?

Основной трудностью работы со статическими массивами является обязательность указания количества их элементов при объявлении. В любом алгоритмическом языке, требующим компиляции (в частности, в Паскале),

границами индексов массива в инструкции array могут быть только константы.

Выход – использование динамических массивов.

Описание динамического массива

Var имя_массива: Array of Array of…Array of тип_элемента;

Ключевые слова Array of записываются в описании столько раз, сколько индексов у массива (т. е. какова его размерность).

По существу объявленное имя_массива является указателем на массив.

Работа с динамическими массивами

1.Распределение памяти под массив: с помощью процедуры SetLength:

SetLength(имя_массива, размер1, размер2, …,размерM).

В скобках указываются размеры массива по первым M (не обязательно всем) индексам.

2.Работа как со статическим массивом. Элементы динамического массива нумеруются с нуля.

3.Освобождение памяти:

имя_массива:=nil ;

установление нулевой длины с помощью SetLength.