Структура подпрограммы


Описание подпрограммы состоит из трех частей: заголовка подпрограммы, локального описания и тела подпрограммы. Заголовок используется, чтобы явно ввести в программу новую подпрограмму и обозначить начало ее описания. Локальные описания представляют собой набор описаний типов, переменных, констант и других подпрограмм, которые действуют только в рамках данной подпрограммы. Тело под-программы — это логический блок begin/end, содержащий операторы и команды Паскаля и реализующий нужную логику работы.


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

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


procedureCompute(X: Integer; S: String);
function Compare(Al, A2: Byte; Stroka: String): Real;
procedureShowMap;
functionGameOver: Boolean;

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

procedureМуРгос
( I: integer; il: integer = 1; i2: integer = 2 );

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

МуРгос( 1, 2 );

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

МуРгос( 1, 2, 2 );


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

В списке параметров перед любой переменной разрешается указывать ключевое слово var. Тогда считается, что данный параметр будет передаваться по имени: то есть копирования значения не происходит, а вместо формального параметра подставляется имя переменной — фактического параметра. (Отсюда следует, что в качестве фактических параметров, подставляемых вместо формальных параметров с ключевым словом var, можно применять только имена переменных.)
Например: procedure MyProc( X: Byte; varY: Byte );

 

Параметр X будет передаваться по значению, параметр Y — по имени. При вызове MyProc( 2+2 , N ) ; операторы в теле процедуры MyProc будут обрабатывать локальную переменную X, имеющую значение 4 (2+2), и переменную Y, которая на самом деле является переменной N из другой части программы. На «физическом» уровне произойдет просто подстановка адреса переменной N. Использование слова var в списке параметров по способу действия аналогично использованию указателя.

При этом, если в теле процедуры значение переменной X будет меняться, то по окончании работы MyProc эта локальная переменная будет удалена из памяти (до следующего вызова процедуры), а вот если произойдет изменение значения переменной Y, то изменится и значение переменной N.

Это потенциально чревато ошибками, так как разработчик может не рассчитывать на то, что во время работы подпрограммы произойдет изменение значения одного из ее параметров. В данном случае переменная Y является не чем иным, как указателем на переменную N, только описан он немного иначе: не с помощью операции Л, а как обычная переменная.

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

typeTBigArray = array [1..100000] of string[50];

то передавать переменную этого типа по значению очень неэффективно, особенно если вызов подпрограммы происходит часто, потому что при этом требуется копировать большие объемы данных. То есть описание

procedureSum( A: TBigArray );


неудачно в плане эффективности (хотя компилятор может самостоятельно выполнить передачу параметра по имени в процессе автоматической оптимизации кода).

Правильнее написать так:

procedureSum( var A: TBigArray );

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

Параметры-константы
Если некоторый параметр будет использоваться в теле подпрограммы только для считывания данных (фактически, как константа), лучше не рассчитывать на воз-можности компилятора, а подсказать ему об этом явно. В этом случае присваивание данному параметру нового значения станет недопустимым.
Подобная «подсказка» осуществляется указанием зарезервированного слова const в списке параметров, что позволяет организовать эффективную обработку соот-ветствующего параметра, не беспокоясь о возможных изменениях его значения.

procedureSum( const A: TBigArray );


Менять значение элементов переменной А в теле процедуры Sum теперь нельзя: компилятор сообщит об ошибке.


Параметры-результаты
В Паскале имеется еще одна возможность передачи параметра по имени — с помощью зарезервированного слова out. Такой параметр может использоваться внутри тела подпрограммы только для присваивания значения (но не для считывания данных). По смыслу использование слова out противоположно использованию слова const.

Если заголовок процедуры описан так:

procedureSum( out A: TBigArray );

то в теле процедуры Sum можно указывать операторы присваивания

А[10000]-:= 'num172855';

но нельзя считывать значения элементов массива

А: х := А[2] * 2; // нельзя!


Преобразования сложных типов


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

Потребность в этом хоть и редко, но все же возникает. Например:

typeTl = array[1..2] ofByte;

var Al: Tl;

A2: array[1..2] of Byte;

Переменные Al и A2 относятся к разным типам, хотя физически (в оперативной памяти) они представлены одинаково. Поэтому переменную А2, обычный массив, можно преобразовать (привести) к типу Tl:Tl(А2)

Такая запись аналогична простому обращению к имени массива А2, только при этом считается, что он имеет новый тип Tl. К элементам массива нового типа можно обращаться, как и раньше, с помощью квадратных скобок: ТКА2) [1]


Параметры без типов

Паскаль позволяет указывать в заголовке подпрограммы параметры без типов (но с предшествующим словом const, var или out).
procedure Sum( const A );

Переменная А в таком случае считается не имеющей никакого типа, и ее нельзя использовать ни в каких выражениях или операторах, не выполнив предварительно преобразование — приведение к нужному типу.
Например, в теле процедуры Sum переменную А можно использовать так: X := Т1(А)[5] * 2;


Передача строк фиксированной длины

Строки можно описывать, как уже говорилось ранее, двумя способами: просто как тип string, или как тип string с конкретной длиной строки в квадратных скобках. Однако указывать строки фиксированной длины в качестве параметров подпрограмм нельзя. Их сначала надо описать как новый тип.

procedure Sum( S: string[50] ); // неверно!

Правильно написать так:

typestring50 = string[50];

procedureSum( S: string50 );








Дата добавления: 2014-12-01; просмотров: 1619;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

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

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.009 сек.