|
Новости |
Глава 9. Процедуры и функции·
Открытые
строковые параметры Процедуры и функции позволяют включать в основной программный блок дополнительные блоки. Каждое описание процедуры или функции содержит заголовок, за которым следует программный блок. Процедура активизируется с помощью оператора процедуры. Функция активизируется при вычислении выражения, содержащего вызов функции, и возвращаемое функцией значение подставляется в это выражение. Примечание:
Определение блока вы можете найти в Главе 8
"Блоки, локальность и область действия". В
данной главе обсуждаются различные способы
описания процедуры или функции и их
параметры. Описания процедурОписание процедуры позволяет связать идентификатор с процедурным блоком. Процедуру можно затем активизировать с помощью оператора процедуры. Заголовки
процедур именуют идентификаторы процедур и
задают формальные параметры (если они
имеются). Примечание:
Синтаксис списка формальных параметров показан
далее в этой главе в разделе "Параметры". Процедура
активизируется с помощью оператора
процедуры, в котором содержатся имя
процедуры и необходимые параметры. Операторы,
которые должны выполняться при запуске
процедуры, содержатся в операторной части
модуля процедуры. Если в содержащемся в
процедуре операторе внутри модуля
процедуры используется идентификатор
процедуры, то процедура будет выполняться
рекурсивно (будет при выполнении
обращаться сама к себе). Приведем
пример описания процедуры: procedure
NumString(N: integer; var S: string); var V:
integer; begin V
:= Abs(N); S
:= ''; repeat S
:= Chr(N mod 10 + Ord('0')) + S; N := N div 10; until
N = 0; if
N < 0 then S := '-' + S; end;
Описания функцийОписание
функции определяет часть программы, в
которой вычисляются и возвращается
значение. Примечание:
Функция не может возвращать процедурный
тип или структурный тип. В
заголовке функции определяется
идентификатор функции, формальные
параметры (если они имеются) и тип
результата функции. Функция
активизируется при вызове функции. При
вызове функции указывается идентификатор
функции и какие-либо параметры, необходимые
для вычисления функции. Вызов функции может
включаться в выражения в качестве операнда.
Когда выражение вычисляется, функция
выполняется и значением операнда
становится значение, возвращаемое функцией. В
операторной части блока функции задаются
операторы, которые должны выполняться при
активизации функции. В модуле должен
содержаться по крайней мере один оператор
присваивания, в котором идентификатору
функции присваивается значение.
Результатом функции является последнее
присвоенное значение. Если такой оператор
присваивания отсутствует или он не был
выполнен, то значение, возвращаемое
функцией, не определено. Если
идентификатор функции используется при
вызове функции внутри модуля-функции, то
функция выполняется рекурсивно. Приведем
далее примеры описаний функции: function
Max(a: Vector; n: integer): extended; var x:
extended; i:
integer; begin x
:= a(1); for
i := 2 to n do if x < a[i] then x := a[i]; Max
:= x; end; function
Power(x: extended; y: integer): extended; var z:
extended; i:
integer; begin z
:= 1.0; i := y; while
i > 0 do begin if
Odd(i) then z := z*x; x
:= Sqr(x); end; Power
:= z; end; Аналогично
процедурам функции могут описываться, как с
ближним типом вызова (near), с дальним типом
вызова (far), опережающие (forward), внешние (external),
ассемблерные (assembler) или подставляемые (inline).
Однако функции прерываний (interrupt) не
допускаются. ПараметрыВ
описании процедуры или функции задается
список формальных параметров. Каждый
параметр, описанный в списке формальных
параметров, является локальным по
отношению к описываемой процедуре или
функции и в модуле, связанным с данной
процедурой или функцией на него можно
ссылаться по его идентификатору. Существует
три типа параметров: значение, переменная и
нетипизированная переменная. Они
характеризуются следующим: 1.
Группа параметров без предшествующего
ключевого слова является списком
параметров-значений. 2.
Группа параметров, перед которыми
следует ключевое слово const и за которыми
следует тип, является списком параметров-констант. 3.
Группа параметров, перед которыми стоит
ключевое слово var и за которыми следует тип,
является списком типизированных
параметров-переменных. 4.
Группа параметров, перед которыми стоит
ключевое слово var или const за которыми не
следует тип, является списком
нетипизированных параметров-переменных. Параметры
строкового типа и массивы могут быть
открытыми параметрами. Параметры-переменные,
описанные с помощью идентификатора OpenString
или с использованием ключевого слова string в
состоянии $P+, являются открытыми строковыми
параметрами. Значение, константа или
параметр-переменная, описанные с помощью
синтаксиса array of T, являются открытым
параметром-массивом. Примечание:
Подробнее об открытых параметрах рассказывается
ниже. Параметры-значенияФормальный
параметр-значение обрабатывается, как
локальная по отношению к процедуре или
функции переменная, за исключением того,
что он получает свое начальное значение из
соответствующего фактического параметра
при активизации процедуры или функции.
Изменения, которые претерпевает формальный
параметр-значение, не влияют на значение
фактического параметра. Соответствующее
фактическое
значение параметра-значения
должно быть выражением и его значение не
должно иметь
файловый тип или
какой-либо структурный тип,
содержащий в себе файловый тип. Фактический
параметр должен иметь тип, совместимый по
присваиванию с типом формального
параметра-значения. Если параметр имеет
строковый тип, то формальный параметр будет
иметь атрибут размера, равный 255. Параметры-константыФормальные
параметры-константы работают аналогично
локальной переменной, доступной только по
чтению, которая получает свое значение при
активизации процедуры или функции от
соответствующего фактического параметра.
Присваивания формальному параметру-константе
не допускаются. Формальный параметр-константа
также не может передаваться в качестве
фактического параметра другой процедуре
или функции. Параметр-константа,
соответствующий фактическому параметру в
операторе процедуры или функции, должен
подчиняться тем же правилам, что и
фактическое значение параметра. В
тех случаях, когда формальный параметр не
изменяет при выполнении процедуры или
функции своего значения, вместо параметра-значения
следует использовать параметр-константу.
Параметры-константы позволяют при
реализации процедуры или функции защититься
от случайных присваиваний формальному
параметру. Кроме того, для параметров
структурного и строкового типа компилятор
при использовании вместо параметров-значений
параметров-констант может генерировать
более эффективный код. Параметры-переменныеПараметр-переменная
используется, когда значение должно передаваться
из процедуры или функции вызывающей
программе. Соответствующий фактический
параметр в операторе вызова процедуры или
функции должен быть ссылкой на переменную.
При активизации процедуры или функции
формальный параметр-переменная замещается
фактической переменной, любые изменения в
значении формального параметра-переменной
отражаются на фактическом параметре. Внутри
процедуры или функции любая ссылка на
формальный параметр-переменную приводит к
доступу к самому фактическому параметру.
Тип фактического параметра должен
совпадать с типом формального параметра-переменной
(вы можете обойти это ограничение с помощью
нетипизированного параметра-переменной). Примечание:
Файловый тип может передаваться только, как
параметр-переменная. Директива
компилятора $P управляет смыслом параметра-переменной,
описываемого с ключевым словом string. В
состоянии по умолчанию ($P-) string
соответствует строковому типу с атрибутом
размера 255. В состоянии $P+ string указывает, что
параметр является открытым строковым
параметром (см. ниже). При
ссылке на фактический параметр-переменную,
связанную с индексированием массива или
получением указателя на объект, эти
действия выполняются перед активизацией
процедуры или функции. Правила
совместимости по присваиванию для
объектного типа применяются также к
параметрам-переменным объектного типа. Для
формального параметра типа T1 фактический
параметр должен быть типа T2, если T2
находится в домене T1. Например, с учетом описаний
Главы 4, методу TField.Copy может передаваться
экземпляр TField, TStrField, TNumField, TZipField или любой
другой экземпляр потомка TField. Нетипизированные параметрыКогда
формальный параметр является
нетипизированным параметром-переменной,
то соответствующий фактический параметр
может представлять собой любую ссылку на
переменную или константу, независимо от ее
типа. Нетипизированный параметр, описанный
с ключевым словом var, может
модифицироваться, а нетипизированный параметр,
описанный с ключевым словом const, доступен
только по чтению. В
процедуре или функции у нетипизированного
параметра-переменной тип отсутствует, то
есть он несовместим с переменными всех
типов, пока ему не будет присвоен
определенный тип с помощью присваивания
типа переменной. Приведем
пример нетипизированных параметров-переменных: function
Equal(var source,dest; size: word): boolean; type Bytes
= array[0..MaxInt] of byte; var N:
integer; begin N
:= 0; while
(N<size) and (Bytes(dest)[N] <> Bytes(source)[N] do
Inc(N); Equal
:= N = size; end; Эта
функция может использоваться для сравнения
любых двух переменных любого размера.
Например, с помощью описаний: type Vector
= array[1..10] of integer; Point
= record x,y:
integer; end; var Vec1,
Vec2: Vector; N:
integer; P:
Point; и
вызовов функций: Equal(Vec1,Vec2,SizeOf(Vector)) Equal(Vec1,Vec2,SizeOf(integer)*N) Equal(Vec[1],Vec1[6],SizeOf(integer)*5) Equal(Vec1[1],P,4) сравнивается
Vес1 с Vес2, сравниваются
первые N элементов Vес1 с первыми
N элементами Vес2, сравниваются первые 5
элементов Vес1 с последними
пятью элементами Vес2 и сравниваются Vес1[1] с
Р.х и Vес2[2]
с P.Y. Хотя
нетипизированные параметры дают вам
большую гибкость, их использование
сопряжено с некоторым риском. Компилятор не
может проверить допустимость операций с
нетипизированными переменными. Открытые параметрыОткрытые
параметры позволяют передавать одной и той
же процедуре или функции строки и массивы
различных размеров. Открытые строковые параметрыОткрытые
строковые параметры могут описываться
двумя способами: ·
с помощью
идентификатора OpenString; ·
с помощью
ключевого слова string в состоянии $P+. Идентификатор OpenString описывается в модуле System. Он обозначает специальный строковый тип, который может использоваться только в описании строковых параметров. В целях обратной совместимости OpenString не является зарезервированным словом и может, таким образом, быть переопределен как идентификатор, заданный пользователем. Когда
обратная совместимость значения не имеет,
для изменения смысла ключевого слова string
можно использовать директиву компилятора
$P+. В состоянии $P+ переменная, описанная с
ключевым словом string, является открытым
строковым параметром. Для
открытого строкового параметра
фактический параметр может быть
переменной любого строкового типа. В
процедуре или функции атрибут размера (максимальная
длина) формального параметра будет тем же,
что у фактического параметра. Открытые
строковые параметры ведут себя также как
параметры-переменные строкового типа,
только их нельзя передавать как обычные
переменные другим процедурам или функциям.
Однако, их можно снова передать как
открытые строковые параметры. В
следующем примере параметр S процедуры
AssignStr - это открытый строковый параметр: procedure
AssignStr(var S: OpenString; begin S
:= '0123456789ABCDEF'; end; Так
как S - это открытый строковый параметр,
AssignStr можно передавать переменные любого
строкового типа: var S1:
string[10]; S1:
string[20]; begin AssignStr(S1);
S1 := '0123456789' AssignStr(S2);
S2 := '0123456789ABCDEF' end; В
AssingStr максимальная длина параметра S та же
самая, что у фактического параметра. Таким
образом, в первом вызове AssingStr при
присваивании параметра S строка усекается,
так как максимальная длина S1 равна 10. При
применении к открытому строковому
параметру стандартная функция Low
возвращает 0, стандартная функция High
возвращает описанную максимальную длину
фактического параметра, а функция SizeOf
возвращает размер фактического параметра. В
следующем примере процедура FillString
заполняет строку заданным символом до ее
максимальной длины. Обратите внимание на
использование функции High для получения
максимальной длины открытого строкового
параметра. procedure
FillStr(var S: OpenString; Ch: Char); begin S[0]
:= Chr(High(S));
задает
длину
строки
FillChar(S[1],
High(S), Ch); устанавливает
число символов emd; Значения
и параметры-константы, описанные с
использованием идентификатора OpenString или
ключевого слова string в состоянии $P+, не
являются открытыми строковыми параметрами.
Они ведут себя также, как если бы были
описаны с максимальной длиной строкового
типа 255, а функция Hingh для таких параметров
всегда возвращает 255. Открытые параметры-массивыФормальный
параметр, описанный с помощью синтаксиса: array
of T является
открытым параметром-массивом. T должно быть
идентификатором типа, а фактический
параметр должен быть переменной типа T, или
массивом, типом элементов которого
является T. В процедуре или функции
формальный параметр ведет себя так, как
если бы он был описан следующим образом: array[0..N
- 1] of T где
N - число элементов в фактическом параметре.
По существу, диапазон индекса фактического
параметра отображается в диапазон целых
чисел от 0 до N - 1. Если фактический параметр -
это простая переменная типа T, то он
интерпретируется как массив с одним
элементом типа T. К
открытому формальному параметру-массиву
можно обращаться только по элементам.
Присваивания всему открытому массиву не допускаются,
и открытый массив может передаваться
другим процедурам или функциям только как
открытый параметр-массив или нетипизированный
параметр-переменная. Открытый
параметр-массив может быть параметром-значением,
параметром-константой и параметром-переменной
и имеет тот же смысл, что и обычные
параметры-значения, параметры-константы и
параметры-переменные. В частности,
присваивания элементам формального
открытого массива-константы не допускаются,
а присваивания элементам формального
открытого массива, являющегося параметром-значением,
не влияют на фактический параметр. Для
открытых массивов-значений компилятор
создает в кадре стека процедуры или функции
локальную копию фактического параметра.
Таким образом, при передаче в качестве
открытых параметров-значений больших
массивов следует учитывать возможное переполнение
стека. При
применении к открытому параметру-массиву
стандартная функция Low возвращает 0,
стандартная функция High возвращает индекс
последнего элемента в фактическом
параметре-массиве, а функция SizeOf
возвращает размер фактического параметра-массива. Процедура
Clear в следующем примере присваивает каждому
элементу массива вещественных значений
ноль, а функция Sum вычисляет сумму всех
элементов массива вещественных чисел.
Поскольку в обоих случаях параметр A
является открытым параметром-массивом,
подпрограммы могут работать с любым
массивом элементов типа Real: procedure
Clear(var A: array of Real); var I:
Word; begin for
I := 0 to High(A) do A[I] := 0; end; function
Sum(const A: array of Real): Real; var I:
Word; S:
Real; begin S
:= 0; for
I := 0 to High(A) do S := S + A[I]; Sum
:= S; end; Когда
типом элементов открытого параметра-массива
является Char, фактический параметр может
быть строковой константой. Например, с
учетом предыдущего описания: procedure
PringStr(const S: array of Char); var I:
Integer; begin for
I := 0 to High(S) do if
S[I] <> #0 then Write(S[I]) else Break; end; и
допустимы следующие операторы процедур: PrintStr('Hello
word'); PrintStr('A'); При
передаче в качестве открытого параметра-массива
пустая строка преобразуется в строку с
одним элементом, содержащим символ NULL,
поэтому оператор PrintStr('') идентичен
оператору PrintStr('#0'). |
(с) Все права защищены. По всем интересующим вопросам прошу писать электронный адрес |