Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Листинг 4.3. Передача параметров по значению




Program ChangingParamsl; Var

I: Integer; Procedure

{Описание целочисленной переменной} Proc (A: Integer);

{Описание процедуры Proc с одним параметром, передаваемым по значению}

Begin

А:= 154,

end; Begin I:= 200; Proc (I);

Proc (80);

End.

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

{Начало раздела описания логики программы}

{Изменение значение переменной 1}

{Вызов процедуры Proc, в качестве параметра

передается значение переменной I, после

окончания работы процедуры значение

переменной сохраняется}

{Вызов процедуры Proc, в качестве параметра

передается целочисленная константа 80, что

допустимо при передаче параметров по значению}

Передача параметров по ссылке. Параметры-переменные

Второй механизм передачи параметров — по ссылке — подразумевает возможность изменения подпрограммой данных вызывающего фрагмен­та программы. Для этого в качестве параметра вызывающий фрагмент должен использовать переменную, адрес которой будет передан в под­программу через стек (см. рис. 4.2). Далее подпрограмма обеспечивает доступ к переданному адресу по имени параметра. Соответственно, из­менения, производимые с параметром в подпрограмме, влияют на ту переменную, которая указана в качестве параметра.

Рис. 4.2. Механизм передачи параметров по ссылке

Для указания компилятору на необходимость передачи параметра по ссылке перед описанием соответствующего параметра указывается спе­циальный модификатор параметра — ключевое слово Var (от англ. Vatriable — переменный):

Procedure (..., Var <Параметр>: <Тип параметра>,...);

Так как при использовании параметров-переменных в подпрограмму должен быть передан некоторый адрес, то в качестве параметра, передаваемого по ссылке, должны использоваться только переменные. Изме­ним предыдущий пример таким образом, чтобы параметр передавался в процедуру по ссылке (см. листинг 4.4).

Листинг 4.4. Передача параметров по ссылке

Program ChangingParams2;

Var

I: Integer; {Описание целочисленной переменной}

Procedure Proc (Var A: Integer);

{Описание процедуры Proc с одним параметром, передаваемым по ссылке}

Begin

 

А:= 154; {Изменение значения параметра, переданного в про­цедуру. Одновременно с этим изменяется значение переменной, переданной в качестве параметра}

End;

Begin {Начало раздела описания логики программы}

I:= 200; {Изменение значение переменной 1}

Proc(I); {Вызов процедуры Proc, в качестве параметра передается адрес переменной I, после окончания работы процедуры, значение переменной изменится и станет равным 154}

 

End.

Параметры, передаваемые по ссылке, называют параметрами-переменны­ми (от англ. Variable parameter — параметр-переменная).

4.2.3. Частные случаи передачи параметров подпрограммам

Параметры по умолчанию

Особенностью Delphi относительно Pascal является возможность исполь­зования параметров по умолчанию. Такие параметры находятся в конце списка параметров и их описания имеют следующий вид:

<Параметр>: <Тип параметра> = <Значение умолчанию>

Подпрограммы, для которых указаны параметры по умолчанию, вы­зываются либо с указанием полного набора параметров, либо с ука­занием набора обязательных параметров и одним или несколькими па­раметрами, имеющими значения' по умолчанию. При этом для того, чтобы передать некоторый параметр, задаваемый умолчанием, следу­ет передать все параметры, находящиеся в списке параметров перед ним Пример использования параметров по умолчанию приведен в листинге 4.5.

Листинг 4.5. Использование параметров по умолчанию

Program UsingFunctions;

Var

s String; {Описание строковой переменной S}

Function GetFullName SurName: String;

FirstName: String = 'имя не введено';

SecondName: String = 'отчество не введено': String; {Описание функции GetFullame с одним обязательным параметром и двумя параметрами, заданными по умолчанию}

 

Begin

Result:= SurName + ' ' +

FirstName + ' ' + SecondName;

{В качестве результата функция возвращает сумму параметров. Если при вызове не задан последний параметр, то вместо него подставляется строка 'отчество не введено', если не задан еще и предпоследний параметр, то вместо него подставляется 'имя не введено'}

End

Begin {Начало раздела описания логики программы}

s= GetFullName ('Иванов');

{В переменной S будет значение 'Иванов

имя не введено отчество не введено'}

s: = GetFullName('Иванов', 'Иван');

{В переменной S будет значение 'Иванов

Иван отчество не введено'}

s:= GetFullName('Иванов', 'Иван', 'Иванович');

{В переменной S будет значение 'Иванов

Иван Иванович' }

End.

Передача по значению параметров ссылочных типов данных

При передаче параметров по значению все содержимое заданной струк­туры данных копируется в локальную память подпрограммы. Однако для ссылочных типов данных их значением, фактически, является адрес па­мяти. Таким образом, при передаче в подпрограмму ссылки, ее значение нельзя изменить, но можно изменить информацию в памяти, на кото­рую эта ссылка указывает.

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

Procedure ChangeParam (P: ^Double); Begin

New(P); End;

В такой реализации процедуры в качестве параметра передается не ад­рес переменной, использованной в качестве параметра, а ее содержимое, то есть адрес, который является значением. Этот адрес заносится в ло­кальную копию переменной, и в подпрограмме используется копия, на­чальное значение которой содержит переданный в качестве параметра адрес. Поэтому подпрограмма, выделяя память под параметр р и занося адрес выделенной памяти в этот параметр, не влияет на переменную, которая была задана в качестве параметра.

Теперь продемонстрируем возможность изменения информации, на ко­торую ссылается переданный параметр:

Procedure ChangeParam (P: ^Double);

Begin

Р^:= 150; {Изменение информации в памяти, на которую указывает параметр, влияет на данные вызывающего фрагмента}

New(P); {Выделение памяти под параметр Р не приводит к изменению адреса в памяти, который является значением переменной, переданной в качестве параметра. Память выделяется под локальную копию параметра}

Р^:= 320; {Изменение информации в памяти, на которую указывает параметр, не влияет на данные вызывающего фрагмента, так как значение параметра уже изменено}

Dispose (P); {Освобождение памяти, выделенной под локальную копию параметра}

End;

Изменим процедуру, сделав параметр передаваемым по ссьлке (листинг 4.6).

Листинг 4.6. Передача по значению параметров ссылочных типов данных

Procedure ChangeParam (Var P:^Double); Begin

Р:= 150; {Изменение информации в памяти, на которую

указывает параметр, влияет на данные

вызывающего фрагмента}

New(P); {Выделение памяти под параметр Р приводит

к потере ссылки на область памяти,

находящейся в параметре при его передаче.

Память выделяется под переменную, заданную

в качестве параметра}

P^:= 320; {Изменение информации в памяти, на которую

указывает параметр, влияет на данные

вызывающего фрагмента}

Dispose(P); {Освобождение памяти, выделенной под

переменную, заданную в качестве параметра}

End;

Аналогична ситуация с параметрами — динамическими массивами, зна­чения элементов которых также может изменить подпрограмма, так как ей передается не копия массива, а ссылка на него", даже если параметр не помечен в описании подпрограммы модификатором Var.

Параметры-константы

Для параметров, передаваемых по значению, предусмотрен модификатор Const, запрещающий изменять значение даже локальной копии данного параметра и передавать его как параметр-переменную в другие подпрог­раммы. Модификатор предназначен для указания компилятору Delphi на неизменяемый характер параметра и позволяет ему создавать более оп­тимальный программный код при использовании строковых параметров и параметров сложных типов данных.

Procedure (..., Const <Параметр>: <Тип параметра>,...);

Таким образом, указание в процедуре Ргос из предыдущего примера модификатора Const вместо модификатора Var приведет к ошибке ком­пиляции с сообщением "Left side cannot be assigned to" - "Ле­вая часть выражения не может быть изменена".

Параметры, описанные с модификатором Const, называются параметра­ми-константами. Пример использования таких параметров приведен в листинге 4.7.

Листинг 4.7. Использование параметров-констант

Procedure OpenFile(Const: FileName: AnsiString);

{Заголовок процедуры OpenFile, строковый параметр FileName передается как константа]

Var

sLocal: AnsiString;

{Описание локальной переменной}

Begin

FileName:= 4heFile.txt';

{Операция недопустима, так как параметр FileName помечен модификатором Const}

sLocal:= FileName; {Операция возможна}

End;

Параметры для заполнения

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

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

Заметим, что обращение к параметрам для заполнения до присвоения им значений в подпрограмме является классическим примером динамичес­кой ошибки. Delphi, освобождая память, занятую под ссылочную пере­менную, задаваемую в качестве параметра, не обнуляет ее адрес. В ре­зультате чего параметр указывает на некоторую область памяти, в которой находятся некоторые данные, причем доступ к ним возможен. Однако при интенсивном использовании системы эта память уже может использо­ваться другой подпрограммой, и доступ к ней вызовет ее сбой.

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

Procedure (..., Out <Параметр>: <Тип параметра>,...);

Пример использования параметров для заполнения приведен в лис­тинге 4.8.

Параметры без указания типа

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

Допустим, в программе описана процедура SaveToFile, принимающая в качестве параметров указатель на данные и целочисленное значение, содержащее размер данных:

Procedure SaveToFile(Buffer: Pointer; Size: Integer);

Для использования такой процедуры, фрагменты программы, которые сохраняют информацию в файл, должны получить адрес сохраняемой структуры и передать его в качестве параметра Buffer. Для этого может быть применен оператор @, возвращающий адрес заданной переменной, и функция sizeOf, возвращающая размер заданной структуры:

Туре

TRec = Record S: String; I: Integer; end; {Описание типа данных, используемого

для хранения информации)

Var

Rec: Tree; {Описание переменной, в которой будет храниться структура, предназначенная для сохранения)





Поделиться с друзьями:


Дата добавления: 2015-10-19; Мы поможем в написании ваших работ!; просмотров: 565 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Велико ли, мало ли дело, его надо делать. © Неизвестно
==> читать все изречения...

2524 - | 2183 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.012 с.