Даже в тех случаях, когда в подпрограмму выделяется однократно производимый набор действий, это оправдано, так как позволяет сократить размеры целостных блоков кода, составляющих программу, то есть сделать программу более понятной и обозримой...
. Механизм подпрограмм, их описание и вызов
В простейшем случае (в ассемблерах) подпрограмма представляет собой последовательность команд (операторов), отдельную от основной части программы и имеющую в конце специальную команду выхода из подпрограммы. Обычно подпрограмма также имеет имя, по которому её можно вызвать, хотя ряд языков программирования допускает использование и неименованных подпрограмм. В языках высокого уровня описание подпрограммы обычно состоит по меньшей мере из двух частей: заголовка и тела. Заголовок подпрограммы описывает её имя и, возможно, параметры, то есть содержит информацию, необходимую для вызова подпрограммы. Тело - набор операторов, который будет выполнен всякий раз, когда подпрограмма будет вызвана.
Вызов подпрограммы выполняется с помощью команды вызова, включающей в себя имя подпрограммы. В большинстве современных языков программирования команда вызова представляет собой просто имя вызываемой подпрограммы, за которым могут следовать фактические параметры.
В следующем примере на языке Паскаль подпрограмма subprog вызывается из основной программы трижды:
program SubProgExample;
// Описание подпрограммы subprog
procedure subprog; // Заголовок, включающий имя подпрограммы
begin // начало тела подпрограммы
WriteLn('Bye');
begin
WriteLn('Hello');
subprog; // 1-й вызов
subprog; // 2-й вызов
subprog; // 3-й вызов
end.
Результатом выполнения такой программы станет вывод строки «Hello» и трёх строк «Bye».
Для сохранения и восстановления контекста выполнения вызывающей процедуры, с целью исключения побочных эффектов, связанных с возможным нежелательным изменением используемых машинных регистров, компилятор формирует для каждой процедуры специальные последовательности команд, называемые прологом и эпилогом процедуры.
Некоторые языки программирования (например, Паскаль, Ада, Модула-2) допускают описание вложенных подпрограмм, то есть помещение подпрограмм внутрь других подпрограмм. Такие вложенные подпрограммы могут использоваться только в той подпрограмме, в которой они описаны. В иных случаях (например, в языке Си) вложение подпрограмм не допускается. Никаких принципиальных преимуществ вложение подпрограмм не даёт, но может быть удобно для более логичной структуризации программы (если какая-то подпрограмма используется только в некоторой другой подпрограмме, логично поместить первую во вторую).
. Параметры подпрограмм. Назначение параметров
Подпрограммы часто используются для многократного выполнения стереотипных действий над различными данными. Подпрограмма обычно имеет доступ к объектам данных, описанным в основной программе (по крайней мере, к некоторым из них), поэтому для того, чтобы передать в подпрограмму обрабатываемые данные, их достаточно присвоить, например, глобальным переменным. Но такой путь не особенно удобен и чреват ошибками.
Для обеспечения контролируемой передачи параметров в подпрограмму и возврата результатов из неё используется механизм параметров. Параметры описываются при описании подпрограммы (в её заголовке) и могут использоваться внутри процедуры аналогично переменным, описанным в ней. При вызове процедуры значения каждого из параметров указываются в команде вызова (обычно после имени вызываемой подпрограммы).
program SubProgExample2;
// Описание подпрограммы subprog
procedure subprog(Line: String); // Заголовок, включающий имя подпрограммы
begin // начало тела подпрограммы
WriteLn(Line);
end; // конец тела подпрограммы
begin
WriteLn('Hello');
subprog('my love,'); // 2-й вызов
subprog('good bye!'); // 3-й вызов
end.
В приведённом примере параметр Line подпрограммы subprog в каждом вызове получает различное значение, благодаря чему выводятся не одинаковые строки, а разные.
Формальные и фактические параметры
Чтобы отличать параметры подпрограммы, описанные в её заголовке и теле, от параметров, указываемых при вызове подпрограммы, используются формальные и фактические параметры. Так, в последнем примере параметр Line в заголовке и теле подпрограммы subprog - это формальный параметр, а строка 'Good bye' , использованная в первом вызове этой подпрограммы - фактический параметр. При вызове подпрограммы фактические параметры, указанные в команде вызова, становятся значениями соответствующих формальных параметров, чем и обеспечивается передача данных в подпрограмму.
Виды параметров в Паскале
Различают четыре вида параметров: - параметры- значения; - параметры- переменные; - параметры- процедуры; - параметры- функции.
Параметры- значения - используются для передачи исходных данных в подпрограмму. Формальные параметры при этом записываются через запятую с указанием их типов. Они получают значения фактических параметров, но не могут передавать свои значения фактическим параметрам.
Параметры- переменные - играют роль как входных, так и выходных (возвращаемых) параметров процедуры. В списке формальных параметров они перечисляются после слова Var с указанием их типов.
Параметры- процедуры - указываются после слова Procedure.
Параметры- функции - . указываются после слова Function.
Способ передачи параметров в подпрограмму
Существует несколько способов передачи параметров в подпрограмму.
·Передача параметров по значению. Формальному параметру присваивается значение фактического параметра. В этом случае формальный параметр будет содержать копию значения, имеющегося в фактическом, и никакое воздействие, производимое внутри подпрограммы на формальные параметры, не отражается на параметрах фактических. Так, если в качестве фактического параметра будет использована переменная, и внутри подпрограммы значение соответствующего формального параметра будет изменено, то фактический параметр останется без изменений.
int func1(int x)
{ x=x+1; return x;}
·Передача параметров по ссылке. В формальный параметр может быть помещён сам фактический параметр (обычно это реализуется путём помещения в формальный параметр ссылки на фактический). При этом любое изменение формального параметра в подпрограмме отразится на фактическом параметре - оба параметра во время вызова подпрограммы суть одно и то же. Параметры, передаваемые по ссылке, дают возможность не только передавать параметры внутрь подпрограммы, но и возвращать вычисленные значения в точку вызова. Для этого параметру внутри подпрограммы просто присваивается нужное значение, и после возврата из подпрограммы переменная, использованная в качестве фактического параметра, получает это значение.
void func2(int &x)
{ x=x+1;}
·Передача параметров через стек. Это фактически разновидность передачи параметра по значению «с ручным приводом», в данном случае отсутствует понятие формальных и фактических параметров. Все параметры лежат на стеке, причём их типы, количество и порядок не контролируются компилятором. Данный подход реализован в языке Форт.
Язык программирования может предоставлять возможность передавать параметры в подпрограммы либо только по значению, либо по значению и по ссылке, либо по имени и значению. В последних двух случаях для различения способов передачи параметра используются отдельные синтаксическая конструкции (в Паскале это ключевое слово var при описании параметра). В действительности, если язык содержит понятие ссылки (указателя), то можно обойтись и без передачи параметра по ссылке (её всегда можно смоделировать, описав параметр типа «ссылка»), но эта возможность удобна, так как позволяет работать с формальным параметром-ссылкой без разыменования, а также повышает надёжность и безопасность программы.
Виды подпрограмм
В языках программирования высокого уровня используется два типа подпрограмм: процедуры и функции.
·Функция - это подпрограмма специального вида, которая, кроме получения параметров, выполнения действий и передачи результатов работы через параметры имеет ещё одну возможность - она может возвращать результат. Вызов функции является, с точки зрения языка программирования, выражением, он может использоваться в других выражениях или в качестве правой части присваивания. Подробнее см. в статье Функция (программирование).
·Процедура - это независимая именованная часть программы, которую после однократного описания можно многократно вызвать по имени из последующих частей программы для выполнения определенных действий.
. Процедуры в Паскале
Структура процедуры аналогична структуре программы и состоит из заголовка и блока (тела процедуры).
PROCEDURE <имя>(<сп. форм. пар.>); <блок> где PROCEDURE - зарезервированное слово процедура; <имя> - имя процедуры, является уникальным, выбирается по общим пра- вилам, желательно чтобы оно отражало смысл процедуры; <сп. форм. пар.> - список формальных параметров т.е. список имен обозначаю- щих исходные данные и результат работы процедуры с указани- ем их типов; <блок> - тело процедуры представляющее разделы описаний и раздел операторов, представляющий составной оператор (совокупность операторов, заключенных в операторные скобки BEGIN END). Разделы описаний процедуры содержат те же разделы что и основная программа, в том числе описания подпрограмм низшего уровня (вложенных).
Глобальные объекты - это объекты, описанные в разделах описаний основной программе. Областью их действия является программа и все, содержащиеся в ней подпрограммы.
Локальные объекты - это объекты, описанные в разделах описаний подпрограммы. Областью их действия является подпрограмма и все содержащиеся в ней подпрограммы низшего уровня.
Локальные описания отменяют глобальные. Оператор вызова процедуры активизирует процедуру. Он имеет вид: <имя>(<сп. факт. пар.>); где: <имя> - имя процедуры; <сп. факт. пар.> - список фактических параметров. Это список конкретных значений, имен и выражений подставляемых вместо формальных параметров и передаваемых в подпрограмму, а так же возвращаемые результаты обработки. Список фактических параметров может отсутствовать. Между формальными и фактическими параметрами существует взаимно - однозначное соответствие по количеству, порядку следования и типу.
Функции в Паскале
Структура описания и механизм использования функции аналогичен процедуре с учетом некоторых особенностей. Описание состоит из заголовка и блока (тела функции).<имя>(<сп. форм. пар.>):<тип>; <блок>; где: FUNCTION - зарезервированное слово функция; <имя> - имя функции, является уникальным, выбирается по общим правилам, желательно чтобы оно отражало смысл функции; <сп. форм. пар.> - список формальных параметров т.е. список имен обозначающих исходные данные функции с указанием их типов; <тип> - тип результата возвращаемого функцией и присваиваемого имени функции; <блок> - тело процедуры представляющее разделы описаний и раздел операторов, представляющий составной оператор (совокупность операторов, заключенных в операторные скобки BEGIN END).
Разделы описаний функции содержат те же разделы что и основная программа, в том числе описания подпрограмм низшего уровня (вложенных). В содержательной части функции ее имени должен быть присвоен результат работы функции. Вызов функции представляет собой операнд (указатель функции) в отличии от процедуры обращение к которой представляет оператор. Он имеет вид: <имя>(<сп. факт. пар.>); где: <имя> - имя функции (указатель); <сп. факт. пар.> - список фактических параметров. Это список конкретных значений, имен и выражений подставляемых вместо формальных параметров и передаваемых в функцию.
Отличие процедуры от функции
1.Функция в отличие от процедуры возвращает единственное скалярное значение
2.Результат вычисления функции присваивается имени, а процедуре входит в список параметров.
.Имя функции имеет тип.
.Обращение к функции представляет операнд, а процедуры оператор.
1.Подпрограмма - Википедия [Электронный ресурс] - Электр. Дан. - Режим доступа: ru.wikipedia.org/wiki/Подпрограмма
.Процедуры и функции в Паскале [Электронный ресурс] - Электр. Дан. - Режим доступа: http://life-prog.ru/view_algoritmleng.php?id=103