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

Вопрос 15.

Модули в Delphi: понятие, описание, использование

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

Приведем общую структуру программного модуля:

Заголовок модуля unit <имя модуля>;

Директивы компилятора {$<директивы>}

Интерфейсная часть interface

Подключение модулей uses <имя>, ..., <имя>;

Константы const ... ;

Типы данных type ... ;

Переменные var ... ;

Заголовки процедур procedure <имя> (<параметры>);

Заголовки функций function <имя> (<параметры>): <тип>;

Часть реализации implementation

Подключение модулей uses <имя>, ..., <имя>;

Константы const ... ;

Типы данных type ... ;

Переменные var ... ;

Реализация процедур procedure <имя>; begin ... end;

Реализация функций function <имя>; begin ... end;

Код инициализации initialization <операторы>

Код завершения finalization <операторы>

end.

Модулем может быть файл с текстом исходного кода, который состоит как минимум из трех частей:

  1. Ключевое слово unit.

Каждый модуль должен начинаться со строки, которая объявляет, что данный блок текста является модулем, и задает имя этого модуля. Имя модуля всегда должно соответствовать имени его файла.

  1. Раздел интерфейса interface. После ключевого слова unit следующей функциональной строкой должно быть ключевое слово interface. Всё, что находится между этой строкой и ключевым словом implementation данного модуля, доступно извне и может использоваться другими модулями и программами. В этом разделе описываются типы данных, константы, переменные, процедуры и функции, которые должны быть доступны программе или другим модулям. Допустимы только объявления, но не реализация процедур и функций.

  2. Раздел реализации implementation следует за разделом интерфейса и начинается с ключевого слова implementation. В разделе implementation реализуется программный код глобальных процедур и функций и описываются локальные данные, процедуры и функции, недоступные основной программе и другим модулям.

Блок initialization является необязательным. Он состоит из операторов и выполняется автоматически непосредственно перед запуском основной программы. Блоки инициализации подключенных к программе модулей выполняются в том порядке, в котором они упоминаются в секции uses.

Блок finalization тоже является необязательным. Он состоит из операторов и выполняется автоматически непосредственно после завершения основной программы. Блоки завершения подключенных к программе модулей выполняются в порядке, обратном порядку подключения модулей в секции uses.

Если модуль не нуждается в инициализации и завершении, блоки initialization и finalization можно опустить.

Вопрос 16. Программирование с использованием динамической памяти. Структура оперативной памяти. Понятие указателя.

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

Память компьютера организована в виде множества ячеек, в которых могут храниться значения; каждая ячейка обозначается адресом. Большинство современных компьютеров, и в том числе все персональные компьютеры, используют размер ячейки состоящей из 8 бит, или "байта". Байт позволяет хранить код одной буквы алфавита или одного символа.

Каждая ячейка памяти имеет адрес, который используется для ее нахождения. Адреса - это числа, начиная с нуля для первой ячейки, увеличивающиеся по направлению к последней ячейке памяти. Поскольку адреса - это те же числа, компьютер может использовать арифметические операции для вычисления адресов памяти. Адрес всегда хранится в двух двухбайтовых словах, называемых адресом сегмента и смещения. Сегмент - это участок памяти, имеющий длину 64 кБ и начинающийся с физических адресов (0,16,32,48,..). Смещение указывает, сколько байт от начала сегмента надо пропустить, чтобы добраться до нужного адреса.

Во многих задачах нужны переменные, которые по мере необходимости можно создавать и удалять во время выполнения программы. С этой целью в языке Delphi организована поддержка так называемых указателей, для которых введен специальный тип данных Pointer. Любая переменная в памяти компьютера имеет адрес. Переменные, которые содержат адреса других переменных, принято называть указателями. Указатели объявляются точно так же, как и обычные переменные:

var

P: Pointer; // переменная-указатель

Переменная P занимает 4 байта и может содержать адрес любого участка памяти, указывая на байты со значениями любых типов данных: Integer, Real, string, record, array и других. Если некоторая переменная P содержит адрес другой переменной N, то говорят, что P указывает на N. Графически это обозначается стрелкой, проведенной из P в N (рисунок 12 выполнен в предположении, что N имеет значение 10):

Теперь мы можем изменить значение переменной N, не прибегая к идентификатору N. Для этого слева от оператора присваивания запишем не N, а P вместе с символом ^:

P: ^Integer;

P^ := 10; // Здесь умышленно опущено приведение типа

Символ ^, записанный после имени указателя, называется оператором доступа по адресу.

Необходимо различать переменную типа указатель и переменную на которую этот указатель ссылается

V

указатель

ar p:^Integer

p

Р^

^-переменная типа Integer

Р

*

При такой записи переменная P по прежнему является указателем, но теперь ей можно присваивать адреса только целых переменных. В данном случае указатель P называют типизированным, в отличие от переменных типа Pointer, которые называют нетипизированными указателями. При использовании типизированных указателей лучше предварительно вводить соответствующий указательный тип данных, а переменные-указатели просто объявлять с этим типом. Поэтому предыдущий пример можно модифицировать следующим образом:

type

PInteger = ^Integer;

var

P: PInteger;

PInteger - это указательный тип данных. Чтобы отличать указательные типы данных от других типов, будем назначать им идентификаторы, начинающиеся с буквы P (от слова Pointer).

В ряде случаев возникает необходимость в указателе без ссылок p: nil;

Каждый указатель может находиться в одном из 3 состояний:

  1. Указатель может содержать пустой адрес(=nil)

  2. Указатель содержит адрес переменной, под которую уже выделена память

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