Процедуры delphi

Delphi 7. Занятие 2_6. Часть 1.

Рассматриваемые вопросы первой части.

  1. Локализация данных через параметры.
  2. Соблюдение порядка параметров.
  3. Принципы передачи данных через параметры.
  4. Параметры-значения.
  5. Параметры-константы
  6. Статическая и динамическая память.

Объявление процедур и функций.

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

Заголовок процедуры состоит из ключевого слова procedure. За ним следует имя процедуры, задаваемое программистом. Оно может состоять из латинских букв, цифр и знака подчёркивания. Имя должно начинаться с буквы.

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

В delphi параметры процедуры или функции могут формироваться несколькими способами.

Объявления параметров

Объявления параметров имеют следующий вид:

имя_параметра:тип_параметра;.

Если имён одного типа указывается несколько, то они перечисляются через запятую. Например:

procedure MyProc(i,j,k:integer; s:string; d1,d2:double; b:boolean)

var x,y:array[1..10] jf integer; //локальные переменные

begin

тело процедуры

End;

Локализация данных через параметры.

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

У процедур и функций есть «двери» и «форточки», через которые они общаются с «внешним миром».

Во первых, это список параметров. Через параметры в процедуры и функции передаются данные для обработки.

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

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

Замечание. Такие переменные «глобальны» в пределах данного модуля. Они не видны из других модулей. Поэтому можно в разных модулях объявлять в этих секциях переменные с одинаковыми именами — программа их не перепутает.

Переменные, объявленные в секции interface, также глобальны для данного модуля.

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

Поэтому имена переменных, объявленных в секции interface, необходимо делать уникальными в пределах программы.

Иначе возникает ошибка «конфликт имён».

В третьих, это обмен данными программы с процедурой по ссылке, о чём речь пойдёт ниже.

Кроме того, функция может возвращать одно значение указанного типа.

delphi передача параметров

Обмен данными через параметры-значения.

Механизм реализации вызова процедуры основан на использовании особым образом организованной области памяти — стеке. Объём стека составляет 64 Кб, что, естественно, накладывает некоторые ограничения на объём передаваемых в процедуру данных.

Стек — это очередь из значений.

Принцип его работы напоминает процесс заполнения автоматного магазина патронами. При этом последний вставленный патрон извлекается первым.

То есть принцип организации выборки из стека — последним вошёл, первым вышел.

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

При этом их значения переписываются в стек.

Аналогично передаются параметры функции delphi при её вызове.

Размещение переменных в памяти.

Принцип организации стека.

Стек организован таким образом, что записать в него может осуществляться только в его «вершину», то есть в первую свободную перед занятыми. ячейку

Таким образом, значения переменных и констант, передаваемых в процедуру, копируются в стек.

При начале работы процедуры эти значения забираются из стека в обратном порядке и подставляются на место переменных, указанных в её шапке.

Например, пусть объявлена процедура:

procedure MyProc(var1,var2:integer; var3:char);

Её вызов может выглядеть следующим образом (пусть х=20):

MyProc(12,х,’A’);

При этом в стек последовательно будут записаны число 12, 20 и код символа ‘A’.

После формирования стека начнётся выполнение процедуры. Последовательно из стека будут считаны значения и присвоены переменным var1=12, var2=20 и var3=65 (код символа латинской «А»)

В дальнейшем эти значения будут подставлены в выражения, содержащие переменные var1, var2 и var3.

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

После выхода из процедуры стек «разрушается» и подготавливается для работы со следующей процедурой.

Таким образом, механизм использования стека разъединяет вызывающую переменную и переменную, используемую в процедуре.

Так, если в процессе работы процедуры присвоить новое значение переменной var2, то изменится значение в стеке, но это никак не отразится на значении самой переменной «х».

Обмен данными через параметры-константы.

Параметры-константы отличаются от параметров-значений тем, что «переменная», объявленная таким образом, не может в процедуре изменить своего значения.

Компилятор не пропустит такую попытку.

Например, объявим:

procedure MyProc(const var1:integer; var2:integer; var3:char);

Если в теле процедуры написать: var1:=var2+10; то компилятор выдаст ошибку: «левой части не может быть присвоено».

В то время как оператор var2:=var1+10; является верным.

Обмен данными через параметры-переменные.

Изменим синтаксис объявления процедуры следующим образом:

procedure MyProc(var v1:integer; v2:integer; v3:char);

В объявлении переменных появилось новое ключевое слово «var».

Оно означает, что переменная v1 будет хранить не значение, а адрес переменной, которая указана в операторе вызова процедуры (переменной y).

Поэтому вызов MyProc(12,х,’A’); недопустим, так как на первом и втором месте обязаны стоять переменные и их адреса должны быть переданы в вызываемую процедуру.

Правильным будет вызов:

MyProc(y,х,’A’);

Таким образом, переменной v1 будет передан адрес переменной y.

Такая запись кардинально изменяет ситуацию. Теперь обе переменные: и v1 в процедуре, и y будут указывать на одну и ту же ячейку памяти (на один и тот же адрес). Следовательно, изменяя v1, мы тем самым изменяем y.

Таким образом можно возвращать результаты работы процедуры, формируя значения var-переменных.

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

При использовании параметров-переменных необходимо быть очень внимательным, чтобы не модифицировать исходные значения!

Например, изменяя в процедуре значение v1, мы тем самым автоматически изменяем значение y. Пусть после выхода из процедуры y должен участвовать в вычислениях со своим первоначальным значением.

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

По поводу функции отметим, что она может возвращать значения не только через var-переменные.

Функция сама может выступать в роли переменной, возвращая значение.

Принципы размещения переменных в памяти.

В самом деле, если написать:

implementation

var xx:integer; //1

procedure MyProc(xx:integer;); //2

var y:integer;

begin

y:=xx+10;

тело процедуры

end;

А затем вызвать процедуру оператором:

MyProc(xx);

то xx в этом вызове и xx в теле процедуры — совершенно разные переменные, хотя имеют одинаковое обозначение.

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

Заметим, что переменная xx будет глобальной переменной, если программа состоит из одного модуля Unit1, то есть она «глобальная» в пределах модуля.

В противном случае, если модулей несколько, она будет «глобальной» в пределах модуля, но локальной по отношению ко всей программе (из других модулей она видна не будет.)

Истинно глобальные переменные объявляются в секции interface, откуда они видны всем модулям программы.

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

Окончательное создании программы — это сборка откомпилированных частей программы в файл .exe.

Такая сборка производится с помощьюпрограммы-компоновщика link.

В интегрированной среде разработки и программа-компилятор, и программа компоновщик встроены в IDE, составляя единый комплекс.

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

Затем использовать отдельный компилятор для перевода текста этих модулей в машинные коды.

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

Ещё раз о сегментах программы.

Как следует из вышесказанного, при сборке программы под её размещение отводится участок памяти, состоящий из частей (сегментов).

Первый сегмент — сегмент кода программы. В нём содержатся команды, которые будут выполняться в процессе работы программы.

Второй сегмент — сегмент данных. Это участок памяти, отведённый для хранения значений переменных.

Третий сегмент отводится под организацию стека.

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

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

Память для динамических переменных отводится в свободном от программ пространстве — «куче».

Операционная система следит за состоянием кучи и непосредственно участвует в процессе распределения памяти.

Далее:

  1. delphi передача в процедуру записей.
  2. delphi передача в процедуру массива.
  3. delphi открытый массив.

Продолжение Delphi 7. Занятие 2_6. Часть 2.

Обновлено: 06.10.2021 — 18:11

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *