- •Лекции (черновики).
- •Интегрированная среда Turbo Pascal (Borland Pascal)
- •Главное меню Turbo Pascal
- •2. Введение в язык Паскаль. Структура программы на Паскале.
- •3. Вывод сообщений на экран.
- •4. Этапы создания программы.
- •Лекция №4 Переменные, типы. Стандартные типы. Операции. Присваивание.
- •1. Идентификаторы.
- •2. Метки.
- •3. Числа.
- •4. Строки.
- •5. Комментарии.
- •6. Описание констант.
- •7. Типы.
- •8. Пользовательские типы.
- •9. Операции.
- •10. Описание переменных. …
- •11. Оператор присваивания. Операторы языка Паскаль.
- •1. Оператор присваивания.
- •2. Оператор процедуры.
- •3. Оператор перехода.
- •4. Условный оператор.
- •If Выражение then Оператор1 else Оператор2;
- •If Выражение then Оператор;
- •5. Составной оператор.
- •6. Оператор выбора.
- •7. Оператор цикла с предусловием.
- •8. Оператор цикла с постусловием.
- •9. Оператор цикла с параметром (со счётчиком).
- •Массивы.
- •Работа со строками.
- •Работа с файлами.
- •Подпрограммы.
- •Процедуры модуля Graph
- •Функции модуля Graph
- •Вывод точки
- •Цветовая шкала
- •Вывод линии
- •Построение прямоугольников
- •Стандартные стили заполнения
- •Вывод текста
- •Вывод численных значений
- •Множества.
- •Указатели
- •Динамические переменные
- •Указатели на процедуры и функции
- •Динамическая память
- •Адреса и указатели
- •Оъбявление указателей
- •Выделение и освобождение динамической память
- •Использование указателей
- •Пример 6.1
- •Процедуры и функции для работы с динамической памятью
- •Администратор кучи
Указатели
Указателем называется переменная, предназначенная для хранения адресов областей памяти. В указателе можно хранить адрес данных или программного кода. Адрес занимает четыре байта и хранится в виде двух слов, одно из которых определяет сегмент, второе — смещение.
Указатели делятся на стандартные и определяемые программистом. Величины стандартного типа pointerпредназначены для хранения адресов данных произвольного типа:
var p : pointer;
Программист может определить указатель на данные или подпрограмму конкретного типа. Как и для других нестандартных типов, это делается в разделе type:
type pword = ^word; { читается как "указатель на word" }
...
var pw : pword;
Такие указатели называются типизированными. Можно описать указатель на любой тип данных, кроме файловых. Тип указателя на данные можно описать и непосредственно при описании переменной:
var pw : ^word;
Для указателей определены только операции проверки на равенство и неравенство и присваивания. Правила присваивания указателей:
Любому указателю можно присвоить стандартную константу nil, которая означает, что указатель не ссылается на какую-либо конкретную ячейку памяти.
Указатели стандартного типа pointer совместимы с указателями любого типа.
Указателю на конкретный тип данных можно присвоить только значение указателя того же или стандартного типа.
Операция @ и функция addr позволяют получить адрес переменной:
var x : word; { переменная }
pw : ^word; { указатель на величины типа word }
...
pw := @w; { или pw := addr(w); }
Для обращения к значению переменной, адрес которой хранится в указателе, примеряется операция разадресации (разыменования), обозначаемая с помощью символа ^:
pw^ := 2; inc(pw^); writeln(pw^);
С величинами, адрес которых хранится в указателе, можно выполнять любые действия, допустимые для значений этого типа.
Стандартные функции для работы с указателями:
addr(x) : pointer — возвращает адрес х (аналогично операции @), где х — имя переменной или подпрограммы;
seg (x) : word — возвращает адрес сегмента для х;
ofs (x) : word — возвращает смещение для х;
cseg : word — возвращает значение регистра сегмента кода CS;
dseg : word — возвращает значение регистра сегмента данных DS;
ptr (seg, ofs : word) : pointer — по заданному сегменту и смещению формирует адрес типа pointer.
Динамические переменные
Динамические переменные создаются в хипе во время выполнения программы с помощью подпрограмм new или getmem. Динамические переменные не имеют собственных имен — к ним обращаются через указатели.
Процедура new(var p : тип_указателя) выделяет в динамической памяти участок размера, достаточного для размещения переменной того типа, на который ссылается указатель p, и адрес начала этого участка заносит в этот указатель.
Функция new(тип_указателя) : pointer выделяет в динамической памяти участок размера, достаточного для размещения переменной базового типа для заданного типа указателя, и возвращает адрес начала этого участка.
new применяется для типизированных указателей.
Процедура getmem(var p : pointer; size : word) выделяет в динамической памяти участок размером в size байт и присваивает адрес его начала указателю p. Если выделить требуемый объем памяти не удалось, программа аварийно завершается. Указатель может быть любого типа.
Пример работы с динамическими переменными.
type pword = ^word;
rec = record
d : word; s : string;
end;
var p1, p2 : pword; p3 : ^rec;
В разделе исполняемых операторов программы запишем операторы:
new(p1); p2 := new(pword); new(p3);
В результате выполнения процедуры new(p1) в хипе выделяется объем памяти, достаточный для размещения переменной типа word, и адрес начала этого участка памяти записывается в переменную p1. Второй оператор выполняет аналогичные действия, но используется функция new. При вызове процедуры new с параметром p3 в динамической памяти будет выделено количество байтов, достаточное для размещения записи типа rec.
Доступ к выделенным областям осуществляется с помощью операции разадресации:
p1^ := 2; p2^ := 4; p3^.d := p1^; p3^.s := 'Вася';
В этих операторах в выделенную память заносятся значения.
Динамические переменные можно использовать в операциях, допустимых для величин соответствующего типа, например:
inc(p1^); p2^ := p1^ + p3^.d;
with p3^ do writeln (d, s);
Для освобождения динамической памяти используются процедуры Dispose и Freemem, причем, если память выделялась с помощью new, следует применять Dispose, в противном случае — Freemem.
Процедура Dispose(var p : pointer) освобождает участок памяти, выделенный для размещения динамической переменной процедурой или функцией New, и значение указателя p становится неопределенным.
Процедура Freemem (var p : pointer; size : word) освобождает участок памяти размером size, начиная с адреса, находящегося в p. Значение указателя становится неопределенным.
Если требуется освободить память из-под нескольких переменных одновременно, можно применять процедуры Mark и Release.
Процедура Mark(var p : pointer) записывает в указатель p адрес начала участка свободной динамической памяти на момент ее вызова.
Процедура Release(var p : pointer) освобождает участок динамической памяти, начиная с адреса, записанного в указатель p процедурой Mark.
При завершении программы используемая ею динамическая память освобождается автоматически.
При работе с динамической памятью часто применяются вспомогательные функции Maxavail, Memavail и Sizeof.