Передача значений как массива
Зместо указания в параметрах при обращении к подпрограмме имени переменной-ассива можно указать непосредственно содержимое этого массива: список значе-ий через запятую в квадратных скобках.
Sum( [1, 5, X, a+b*2] );
Передача массива вариантного типа
Массив, описанный как array[1..MaxNum] ofVariant; может быть передан в качестве параметра в подпрограмму, если этот параметр описан как array of const:procedureSum( A: array of const ),
Внутри тела подпрограммы надо анализировать перед обработкой тип каждого элемента этого массива.
Способы вызова подпрограмм
Подпрограммы с точки зрения прикладного программиста вызываются всегда оди-наково, но машинный код, который создается компилятором, для разных подпрограмм может отличаться. Это зависит от целей применения конкретной подпрограммы. Она может использоваться:
>> в рамках разрабатываемой прикладной программы;
>> как функция, доступная из динамической библиотеки .DLL;
>> как процедура, вызываемая из внешних программ или из Windows и т. д.
Для каждого из таких нестандартных случаев вслед за заголовком подпрограммы (за точкой с запятой) должно следовать одно из ключевых слов.
Таблица 1.10. Ключевые слова в заголовке подпрограмм
____________________________________________________________________
Ключевое слово Способ передачи параметров
_____________________________________________________________________
pascalСтандартный (параметры помещаются в стек)
registerСпособ, применяемый по умолчанию. Аналогичен использованию
ключевого слова pascaL но параметры передаются с помощью трех регистров
процессора, а не помещаются в стек (область оперативной памяти), что обычно приводит к повышению быстродействия программы
cdeclВ соответствии с соглашениями компиляторов для языков
программирования С и С++. Применяется, когда происходит обращение к
динамическим библиотекам DLL, написанным на этих языках
stdcallВ соответствии с соглашениями Windows
safecallИспользуется при работе с компонентными технологиями
_____________________________________________________________________
При использовании ключевых слов registerи pascal вычисление параметров выполняется слева направо и располагаются они в оперативной памяти перед вызовом подпрограммы в таком же порядке. При использовании ключевых слов cdecl, stdcallи safecallпараметры располагаются в обратном порядке (справа налево).
procedure Sum( A: array of const ); stdcall;
Существует еще одно зарезервированное слово Паскаля, forward, которое, при указании вслед за заголовком, говорит компилятору о том, что в данном месте расположен только заголовок подпрограммы, а все ее описание находится в исходном тексте далее. Такое описание обычно применяют, если в тексте имеется несколько подпрограмм, которые вызывают друг друга по кругу. Например, из процедуры Р1 вызывается процедура Р2, а из процедуры Р2 — процедура Р1.
Паскаль требует, чтобы любой идентификатор, будь то переменная или подпрограмма, был предварительно, до первого своего использования, описан. В таком круговом процессе (пример условный, потому что приведенная схема может привести к бесконечной цепочке вызовов) процедура Р2, вызываемая в теле процедуры Р1, расположенной выше в исходном тексте, еще не описана, следовательно, обращаться к ней нельзя и компилятор сообщит, что обнаружен неопределенный идентификатор.
Неправильно:
Подпрограммы:
procedurePI;
begin
P2;
end;
procedureP2;
begin
PI;
end;
Правильно:
procedureP2; forward;
procedurePI;
begin
P2;
end;
procedureP2 ;
begin
PI;
end;
Теперь компилятор знает, как выглядит заголовок процедуры Р2, и может корректно сгенерировать машинный код для обращения к ней.
Перегружаемые подпрограммы
Хотя в Паскале не допускается использование одинаковых названий для переменных, констант и других идентификаторов, для локальных переменных и подпрограмм делается исключение. Так как в Паскале предъявляются строгие требования к типам данных, обращаться к подпрограмме, формальные параметры которой имеют тип Integer, с фактическими параметрами, имеющими тип Real, нельзя. Однако при решении задачи подчас бывает необходимо, чтобы подпрограмма с одним и тем же именем работала с разными типами данных.
Здесь есть два способа действий: либо использовать данные типа Variant (что чревато ошибками преобразования, снижает общую эффективность программы и требует от разработчика повышенной бдительности), либо применить перегружаемые подпрограммы. Они отличаются от обычных подпрограмм тем, что имеют совпадающие имена, а различаются только типами аргументов. Чтобы указать компилятору, что конкретная подпрограмма — перегружаемая, надо вслед за ее заголовком указать зарезервированное слово overload.
При вызове такой подпрограммы компилятор по типам параметров автоматически определит, какую же подпрограмму конкретно надо использовать в данном месте.
procedureOvl( X: Real ); overload;
begin
. . .
end ;
procedureOvl( X: Byte ); overload;
begin
. . .
end;
Ovl( 1 ); // вызывается процедура Ovl( X: Byte )
Ovl( 1.0 ); // вызывается процедура Ovl( X: Real )
Необходимое требование к перегружаемым процедурам состоит в том, чтобы списки параметров совпадали во всем, за исключением типов переменных.
Надо особенно осторожно использовать перегружаемые подпрограммы с параметрами по умолчанию. Например:
procedureOvl( X: Byte; Y: Real = 1 ); overload;
begin
. . .
end;
procedureOvl( X: Byte ); overload;
begin
. . .
end;
При вызове
Ovl(1)
компилятор не сможет понять, какую из двух процедур ему вызывать, и сообщит об ошибке.
Локальное описание
Сразу за заголовком подпрограммы следует локальное описание типов, переменных и констант, локальных для данной подпрограммы и существующих только в ее границах. Такое описание подчиняется обычным правилам Паскаля. В нем разрешается использовать слова type, var и const. Локальное описание может быть опущено.
Вложенные подпрограммы
Помимо обычных описаний, внутри подпрограммы допускается объявлять также локальные подпрограммы, к которым можно обращаться (вызывать) только из тела «родительской» подпрограммы. При этом локальная подпрограмма может свободно обращаться к любым локальным описаниям (переменным, типам), которые расположены до описания данной подпрограммы.
Такая возможность полезна, когда во время кодирования подпрограмма начинает непредвиденно разрастаться. Ее приходится делить на более мелкие фрагменты, которые в то же время желательно не выносить за пределы текущей подпрограммы, чтобы иметь возможность пользоваться ранее сделанными локальными описаниями. Например:
procedureDemo;
type Tl = array[1..2] of Real;
varD, Dl: Tl;
S: Real;
procedureInDemo;
begin
Dl := D;
S := Dl[l] + Dl[2]
end;
begin
. . .
end;
Уровень вложенности локальных подпрограмм неограничен. Тело
Дата добавления: 2014-12-01; просмотров: 1457;