№53 Функции и процедуры в языках программирования. Передача параметров по значению и по ссылке


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

В языках программирования высокого уровня используется два типа подпрограмм: процедуры и функции.

    * Функция — это подпрограмма специального вида, которая, кроме получения параметров, выполнения действий и передачи результатов работы через параметры имеет ещё одну возможность — она может возвращать результат. Вызов функции является, с точки зрения языка программирования, выражением, он может использоваться в других выражениях или в качестве правой части присваивания.
    * Процедура — это любая подпрограмма, которая не является функцией.

Подпрограммы, входящие в состав классов в объектных языках программирования, обычно называются методами. Этим термином называют любые подпрограммы-члены класса, как функции, так и процедуры; когда требуется уточнение, говорят о методах-процедурах или методах-функциях.


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

Функция — в программировании — это поименованная часть программы, которая может вызываться из других частей программы столько раз, сколько необходимо. Функция, в отличие от процедуры, может возвращать значение.

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

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


Передача параметра

Передача параметра возможна по значению и по ссылке. Иногда также используют выражение «передача параметра по адресу». Ниже приведён пример, иллюстрирующий различия этих способов.

Передача параметра по значению

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

Передача параметра по адресу

Если необходимо именно изменить переменную из внешней, по отношению к вызываемой функции, области видимости, можно копировать адрес переменной, подлежащей изменению. Соответственно при вызове функции g(&x) приходится использовать операцию взятия адреса. Эта техническая деталь отвлекает внимание программиста от логики прикладной программы, однако в случаях невозможности передачи по ссылке может оказаться единственным решением.

Можно заметить, что передача параметра по адресу является частным случаем передачи по значению: передаваемым значением является адрес, по которому можно найти другое значение — значение переменной x.

Передача параметра по ссылке

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

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

Если функция возвращает значение по ссылке (например в виде "return *this;"), то её вызов можно использовать слева от оператора присваивания (смотри также L-выражение).

В случае если передача по ссылке используется именно как средство увеличения быстродействия, но изменение параметра нежелательно, можно использовать передачу по ссылке константного объекта.

Таким образом можно ожидать, что примерная программа напечатает (если закоментировать ошибочную строку) "0010 022 233 333".

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

Фактический или формальный

По способу применения различают:

    * фактический параметр — аргумент, используемый как значение (число, символ и т. д.);
    * формальный параметр — аргумент, используемый как ячейка памяти (название переменной, указатель на переменную), выступающее в качестве идентификатора этого значения, принимаемое функцией.

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

Особенности использования:

    * формального парметра:
          o аргумент должен быть определён вне функции;
          o параметр формирует побочный эффект;
          o размера вектора может неописываться, тогда доступ осуществляеся либо по указателям, либо с помощью специальных средств языка;
    * фактического параметра-переменной — копировании в оперативную память. Если фактический параметр не подлежит изменению, для экономии памяти его можно оформить контантой (константы вычисляюстя и инициализируются на этапе компиляции).

Поддержка: некоторые языки не имеет специальных лексических средств поддержки формирования формальных, например Си/Си++, или фактических параметров.
Пример на языке Паскаль:  [показать]

Program parameter(output);
var iActual, iFormal: Integer;
Function actual_p(n: Integer): Integer;
begin {actual_p}
 n := 1;
 actual_p := n;
end {actual_p};
Function formal_p(var n: Integer): Integer;
begin {formal_p}
 n := 1;
 formal_p := n;
end {formal_p};
begin
 iActual := 0;
 iFormal := 0;
 WriteLn('Начальное значение переменной: ', iActual);
 WriteLn('Аргумент передан как фактический параметр и изменён:', actual_p(iActual));
 WriteLn('Конечное значение переменной: ', iActual);
 WriteLn('Начальное значение переменной: ', iFormal);
 WriteLn('Аргумент передан как формальный параметр и изменён:', formal_p(iFormal));
 WriteLn('Конечное значение переменной: ', iFormal);
 ReadLn; { Ожидание нажатия кнопики и enter, для закрытия окна. }
end.

Пример на языке С++:  [показать]

#include<iostream.h>
int actual_p(int n)
{n = 1;
 return(n);
}
int formal_p(int &n)
{n = 1;
 return(n);
}
int main(void)
{int iActual = 0;
 int iFormal = 0;
 cout << "Начальное значение переменной: " << iActual << endl;
 cout << "Аргумент передан как фактический параметр и изменён: " << actual_p(iActual) << endl;
 cout << "Конечное значение переменной: " << iActual << endl;
 cout << "Начальное значение переменной: " << iFormal << endl;
 cout << "Аргумент передан как формальный параметр и изменён: " << formal_p(iFormal) << endl;
 cout << "Конечное значение переменной: " << iFormal << endl;
 int i; cin >> i; /* Ожидание нажатия кнопики и enter, для закрытия окна. */
 return 0;
}

Результат работы программ:

Начальное значение переменной: 0
Аргумент передан как фактический параметр и изменён: 1
Конечное значение переменной: 0
Начальное значение переменной: 0
Аргумент передан как формальный параметр и изменён: 1
Конечное значение переменной: 1

Как видно из работы программ:

    * фактический параметр — значение аргумента;
    * формальный параметр — имя арумента, то есть указатель на переменную.



Hosted by uCoz