Тема: Процедуры и функции
Паскаль позволяет структурировать программу, отделив ее функционально независимые части. Отдельные, функционально независимые части программы называют подпрограммами(процедурами и функциями).
Название «подпрограмма» означает, что она подобна и подчинена программе.
Подпрограммы решают очень важные задачи, значительно облегчая программирование:
избавляют от необходимости многократно повторять в тексте программы аналогичные фрагменты;
улучшают структуру программы, облегчая ее понимание при разборе;
повышают устойчивость к ошибкам программирования и непредвиденным последствиям при модификациях.
Подпрограммы могут быть:
стандартными, т.е. определенными системой Паскаль;
пользовательскими, т.е. разработанными собственно пользователем.
Существует два способа объединения подпрограмм и программ:
текст подпрограмм может быть приведен в разделе описаний использующей их программы до слова begin, с которого начинается тело самой программы(это важно!);
подпрограммы группируются в отдельных файлах, имеющих специальную структуру – модулях. Для того чтобы основная программа могла использовать модуль, он должен быть подключен к основной программе.
Первый способ используется, когда программа в целом не слишком велика, а ее подпрограммы, по-видимому, не будут использованы в других программах.
Второй способ желателен для тех программ, которые составляют Ваш технологический задел по программированию и могут использоваться в других программах. Кроме того, оформление отдельных модулей желательно для больших программ, когда текст становится неудобным для восприятия.
С одной стороны, вопрос о том, какие частные алгоритмы должны быть вынесены в подпрограммы, во многом определяется привычками программиста. С другой стороны, огромное количество разработанных программ позволяет указать на типичные ситуации и сформулировать общие принципы выделения подпрограмм:
Когда Вы несколько раз перепишете в программе одни и те же последовательности команд, необходимость введения подпрограммы приобретет характер острой внутренней потребности.
Иногда слишком много мелочей закрывает главное. Полезно убрать в подпрограмму подробности, заслоняющие смысл основной программы.
Полезно разбить длинную программу на составные части – просто как книгу разбивают на главы. При этом основная программа становится похожа на оглавление.
Бывают сложные частные алгоритмы. Полезно отладить их отдельно в небольших тестирующих программах. Включение программ с отлаженными алгоритмами в основную программу будет легким, если они оформлены как подпрограммы.
Все, что Вы сделали хорошо в одной программе, Вам захочется перенести в новые. Для повторного использования частей программы лучше сразу выделять полезные алгоритмы в подпрограммы.
Структура текста подпрограммысоответствует структуре текста основной программы:
Следует обратить внимание на два отличия в описании основной программы и подпрограммы:
подпрограмма начинается с заголовка, содержащего имя подпрограммы, передаваемые в нее и возвращаемые от нее параметры. Заголовок подпрограммы отличается от заголовка основной программы;
подпрограмма заканчивается точкой с запятой, а не точкой.
Чем отличаются процедуры и функции?
И процедура, и функция – подпрограмма, которая создается для выделения в отдельный завершенный логический блок некоторого вспомогательного алгоритма. Обычно функция используется в том случае, когда результатом подпрограммы должна быть единственная скалярная (простая) величина. Отличие между процедурой и функцией проявляется также при вызове их из основной программы.
Заголовки процедуры и функции имеют вид:
Procedure<имя_процедуры> (<список формальных параметров>);
Function<имя_функции> (<список формальных параметров>): <тип результата>;
Список формальных параметров – это имена переменных с указанием их типов, над которыми подпрограмма осуществляет действия.
Пример заголовков процедуры и функции:
Procedure primer1 (x, y: real; z: integer);
Function primer2 (n, m: byte): integer;
Вызов подпрограммыпроисходит при каждом употреблении ее имени в основной программе. При вызове подпрограммы начинают выполняться ее операторы до завершающего словаendили специального выхода из подпрограммы –exit. После выхода из подпрограммы управление передается команде, следующей за обращением к подпрограмме.
Отличия процедуры от функции связаны со способом вызова.
Для вызова процедурыприводится ее имя и в скобках приводится список передаваемых и получаемых параметров. Вызов процедуры – оператор(это важно!).
Вызов функциипроизводится по ее имени и списку параметров, но, в отличие от процедуры, результат функции имеет определенное значение, поэтому функции используются не как операторы, а как выражения или операнды в выражениях(это важно!). Для того чтобы функция получила численное значение, в теле функции необходимо присвоить ей это значение.
Пример обращения к процедуре и функции:
Primer1 (sin(2),k, 3);
При вызове подпрограммы (процедуры или функции) после ее имени в скобках указываются фактические параметры. Фактическими параметрами могут быть как конкретные значения, так и переменные или даже результат выражения. Последовательность фактических параметров, их количество и их тип должны точно совпадать с формальными параметрами подпрограммы. Значения фактических параметров на момент обращения к подпрограмме должны быть определены.
Передача параметров по ссылке и по значению
При передаче параметров по значению в подпрограмме создаются переменные, в соответствии с объявлениями в заголовке. Эти переменные существуют только на время работы подпрограммы.
При вызове процедуры фактические параметры, передаваемые по значению, могут быть записаны как константы, переменные или выражения.
В начале выполнения подпрограммы копии значений этих констант, переменных и выражений присваиваются временным переменным подпрограммы. Когда подпрограмма завершается, используемые в ней переменные не сохраняются. Это значит, что передача параметров по значению имеет смысл для передачи данных в подпрограмму, но не для передачи полученных результатов из нее.
Пример описания формальных параметров, передаваемых по значению:
Procedure primer (x, y: integer; z: real);
При передаче параметров по ссылке основная программа передает в подпрограмму не значение переменной, а ссылку на нее, следовательно, память под передаваемую по ссылке переменную не отводится. Подпрограмма, производя некоторые действия с переменной, принявшей ссылку на место памяти основной программы, где расположена переменная, в действительности производит действия с переменной основной программы. Поэтому после завершения процедуры изменения, совершенные с переменной основной программы, сохраняются. Этот механизм используется для получения результатов от подпрограммы.
При вызове процедуры параметры, передаваемые по ссылке, не могут быть заданы ни константой, ни выражением, т.к. они не имеют адреса для передачи. Параметры, передаваемые по ссылке, при вызове процедуры задаются переменной.
В заголовке процедуры список параметров, принимающих значения по ссылке, начинается служебным словом var.
Пример описания формальных параметров, передаваемых по ссылке:
Procedure primer1 (var k,l: byte; var d: integer);
Решение задачи с использованием подпрограмм
Задача: треугольник задан координатами своих вершин. Составить программу вычисления его площади.
Решение этой задачи удобно представить в виде следующих этапов:
Ввод последовательно координат трех вершин: x1,y1,x2,y2,x3,y3.
Вычисление длины первой стороны
Вычисление длины второй стороны
Вычисление длины третьей стороны
Вычисление площади по формуле Герона
Вывод на экран полученного значения площади.
Из приведенного выше плана решения задачи видно, что в пунктах 2-4 будут выполняться одни и те же действия только с разными координатами вершин. Удобно оформить эти вычисления в виде подпрограммы. Так как длина стороны – это вещественное число, то ее можно вычислять с помощью подпрограммы-функции. При этом для начала можно продумать лишь название функции, ее параметры и тип результата, а детали реализации записать чуть позже. Иначе говоря, следует пока написать «пустую» функцию, чтобы понять для начала ход решения основной задачи.
Итак, пусть наша функция называется storona. Для вычисления стороны треугольника нужно передать в подпрограмму координаты двух вершин. Пусть формальные параметры называютсяa1,b1,a2,b2 и имеют вещественный тип (real). Тип результата функции также будет вещественным.
Тогда начальный вариант программы будет выглядеть следующим образом:
Writeln(‘Введите координаты первой вершины’);
Writeln(‘Введите координаты второй вершины’);
Writeln(‘Введите координаты третьей вершины’);
Writeln(‘площадь треугольника равна:’,s);
После того, как в основной программе выделены подзадачи, продуман план решения, решен основной вопрос, какие данные передаются в подпрограмму и что должно быть получено в результате ее работы, можно детально продумать алгоритм работы подпрограммы.
Для вычисления длины стороны в функции можно описать локальную (определенную только внутри функции) переменную вещественного типа, пусть она называется d.
Function storona (a1, b1, a2, b2: real): real;
D:= sqrt(sqr(a1- a2) +sqr(b1-b2));
Вот теперь наша задача полностью решена.
Эту же задачу можно решить с использованием подпрограммы-процедуры. Начинать решение задачи рекомендуется так же, как и в предыдущем случае. Сначала определить название процедуры, передаваемые в нее параметры, способ получения результата из процедуры. Тело процедуры пока можно сделать пустым. Затем написать основную программу, в которой определить точки обращения к процедуре и значения фактических параметров.
Пусть наша процедура называется dlina. Для вычисления длины стороны треугольника в процедуру необходимо передать значения координат двух вершин, поэтому в списке формальных параметров в заголовке процедуры нужно описать 4 параметра-значения вещественного типа:a1,b1,a2,b2. Для передачи полученного значения в основную программу нужно описать в заголовке параметр-переменную, принимающий ссылку, назовем этот параметрd(необходимо помнить, что в заголовке процедуры перед этим параметром ставится служебное словоvar).
Тогда начальный вариант программы будет выглядеть следующим образом:
Writeln(‘Введите координаты первой вершины’);
Writeln(‘Введите координаты второй вершины’);
Writeln(‘Введите координаты третьей вершины’);
Writeln(‘площадь треугольника равна:’,s);
Обратите еще раз внимание на различие в вызове подпрограммы-функции и подпрограммы-процедуры. Обращение к функции использовалось в операторе присваивания как выражение, а обращение к процедуре – это оператор.
Теперь можно наполнить содержанием саму процедуру:
Procedure dlina (a1, b1, a2, b2: real; var d: real);
D:= sqrt(sqr(a1- a2) +sqr(b1-b2));
Область действия переменных, взаимодействие блоков
В программе может быть описано сколько угодно блоков (подпрограмм). Внутри этих блоков могут быть описания других блоков. Важно знать, откуда и какие блоки могут быть вызваны.
«Блок – это дом с зеркальными стенами. Изнутри видно все, что делается снаружи. Внутрь заглянуть нельзя».
Рассмотрим программу с процедурами различного уровня вложенности. Мы получим иерархию описаний:
Procedure A;
Подпрограмма любого уровня имеет обычно описание множества констант, переменных, типов и вложенных подпрограмм низшего уровня.
Считается, что все имена, описанные внутри подпрограммы, локализуютсяв ней, т.е. они как бы «невидимы» снаружи подпрограммы. Таким образом, со стороны операторов, использующих обращение к подпрограмме, она (подпрограмма) трактуется как «черный ящик», в котором реализуется тот или иной алгоритм. Все детали этой реализации скрыты от глаз пользователя и поэтому недоступны ему.
В рассмотренном выше примере из основной программы можно обратиться к подпрограммам А и В, но нельзя вызвать ни одну из вложенных в них процедур А1, А2, В1, В2 и В21.
При входе в подпрограмму низшего уровня становятся доступными не только описанные в ней имена, но и сохраняется доступ ко всем именам верхнего уровня. Так, например, из подпрограммы В21 мы можем вызвать подпрограмму А, использовать имена, объявленные в основной программе, в подпрограмме В, и обратиться к ним.
При взаимодействии подпрограмм одного уровня вступает в действие основное правило Паскаля: любая подпрограмма перед использованием должна быть описана. Поэтому из процедуры В можно вызвать процедуру А. Из процедуры А вызвать В невозможно (точнее такая возможность появляется только с использованием опережающего описания).
Продолжая образное сравнение, подпрограмму можно уподобить ящику с непрозрачными стенками и дном, но с полупрозрачной крышей: из подпрограммы можно «смотреть» только вверх и нельзя вниз; т.е. подпрограмме доступны только те объекты верхнего уровня, которые описаны до описания данной подпрограммы. Эти объекты называются глобальнымипо отношению к подпрограмме.
Имена локальных переменных могут совпадать с именами глобальных переменных. Если в подпрограмме описана (локализована) переменная с тем же именем, что и глобальная, то в этом случае на время действия подпрограммы локальная переменная «закрывает» глобальную и делает ее недоступной, т.е. значение глобальной переменной на время действия подпрограммы «замораживается».
Память для локальных, т.е. описанных в подпрограмме, переменных выделяется на время действия подпрограммы в специальной области, называемой стеком. При завершении подпрограммы память освобождается, поэтому все внутренние результаты работы подпрограммы не сохраняются от одного обращения к другому.
Чем отличаются понятия функции, процедуры и метода в программировании?

1 — в контексте парадигм, из данных понятий уникально одно Метод, как уже было сказано D3lphi, это нечто принадлежащее классу. класс, в свою очередь, это фундаментальное понятие ООП основанного на классах (шарм ситуации в том, что ООП бывает тоже разное ;))
в этом случае чаще принято уточнять что метод — это один из видов челнов класса (бывают еще поля, свойства, интерфейсы но это уже контекст конкретного языка) .. и как верно заметил Griboks — он реализуется функцией или процедурой
но .. есть много языков, где понятия метод нет вообще
а еще есть функциональное программирование .. эта парадигма частично присутствует во многих современных языках, однако есть языки, где любой код только функция
2 — из контекста языков:
понятие процедура в явном виде, чаще всего употребляют преподаватели, которые сами учились на языках типа Fortran, Pascal или родственных, и либо не имели другого опыта вообще, либо иной опыт был на много скромнее
сейчас доминируют языки, основывающиеся на Си синтаксисе, даже java и js в данном вопросе станут родственниками классического Си
а в нем нет понятия процедуры, только функции.. а на случай, когда функция не обязана возвращать какую либо величину, просто указывается тип возвращаемого значения void
смешение всего этого на примере C# — в этом языке, все есть объект. а любой исполняемый код это метод, и методы реализуются только функциями (в тч void функциями)
What is the difference between a "function" and a "procedure"?
Generally speaking, we all hear about the functions or procedures in programming languages. However, I just found out that I use these terms almost interchangeably (which is probably very wrong).
So, my question is:
What is the difference in terms of their functionality, their purpose and use?
An example would be appreciated.
![]()
18 Answers 18
A function returns a value and a procedure just executes commands.
The name function comes from math. It is used to calculate a value based on input.
A procedure is a set of commands which can be executed in order.
In most programming languages, even functions can have a set of commands. Hence the difference is only returning a value.
But if you like to keep a function clean, (just look at functional languages), you need to make sure a function does not have a side effect.
![]()
dale/ada/aln/8_subprograms.html), where the second paragraph of that page starts with "Procedures in Ada are similar to those in Pascal. A procedure can contain return statements.". Is this an error in the text? Or does it mean that it can have return statements but don't return any values?
This depends on the context.
In Pascal-like languages, functions and procedures are distinct entities, differing in whether they do or don’t return a value. They behave differently wrt. the language syntax (eg. procedure calls form statements; you cannot use a procedure call inside an expression vs. function calls don’t form statements, you must use them in other statements). Therefore, Pascal-bred programmers differentiate between those.
In C-like languages, and many other contemporary languages, this distinction is gone; in statically typed languages, procedures are just functions with a funny return type. This is probably why they are used interchangeably.
In functional languages, there is typically no such thing as a procedure — everything is a function.
Although you should note that the C Standard doesn’t talk about procedures, only functions.
In general, a procedure is a sequence of instructions.
A function can be the same, but it usually returns a result.
There’s a term subroutine or subprogram which stands for a parameterized piece of code that can be called from different places.
Functions and procedures are implementations of those. Usually functions return values and procedures don’t return anything.
Basic Differences
- A Function must return a value but in Stored Procedures it is optional: a procedure can return 0 or n values.
- Functions can have only input parameters for it, whereas procedures can have input/output parameters.
- For a Function it is mandatory to take one input parameter, but a Stored Procedure may take 0 to n input parameters.
- Functions can be called from a Procedure whereas Procedures cannot be called from a Function.
Advanced Differences
- Exceptions can be handled by try-catch blocks in a Procedure, whereas a try-catch block cannot be used in a Function.
- We can go for Transaction Management in a Procedure, whereas in a Function we can’t.
In SQL:
- A Procedure allows SELECT as well as DML ( INSERT , UPDATE , DELETE ) statements in it, whereas Function allows only SELECT statement in it.
- Procedures can not be utilized in a SELECT statement, whereas Functions can be embedded in a SELECT statement.
- Stored Procedures cannot be used in SQL statements anywhere in a WHERE (or a HAVING or a SELECT ) block, whereas Functions can.
- Functions that return tables can be treated as another Rowset. This can be used in a JOIN block with other tables.
- Inline Functions can be thought of as views that take parameters and can be used in JOIN blocks and other Rowset operations.
This is a well-known old question, but I’d like to share some more insights about modern programming language research and design.
Basic answer
Traditionally (in the sense of structured programming) and informally, a procedure is a reusable structural construct to have «input» and to do something programmable. When something is needed to be done within a procedure, you can provide (actual) arguments to the procedure in a procedure call coded in the source code (usually in a kind of an expression), and the actions coded in the procedures body (provided in the definition of the procedure) will be executed with the substitution of the arguments into the (formal) parameters used in the body.
A function is more than a procedure because return values can also be specified as the «output» in the body. Function calls are more or less same to procedure calls, except that you can also use the result of the function call, syntactically (usually as a subexpression of some other expression).
Traditionally, procedure calls (rather than function calls) are used to indicate that no output must be interested, and there must be side effects to avoid the call being no-ops, hence emphasizing the imperative programming paradigm. Many traditional programming languages like Pascal provide both «procedures» and «functions» to distinguish this intentional difference of styles.
(To be clear, the «input» and «output» mentioned above are simplified notions based on the syntactic properties of functions. Many languages additionally support passing arguments to parameters by reference/sharing, to allow users transporting information encoded in arguments during the calls. Such parameter may even be just called as «in/out parameter». This feature is based on the nature of the objects being passed in the calls, which is orthogonal to the properties of the feature of procedure/function.)
However, if the result of a function call is not needed, it can be just (at least logically) ignored, and function definitions/function calls should be consistent to procedure definitions/procedure calls in this way. ALGOL-like languages like C, C++ and Java, all provide the feature of «function» in this fashion: by encoding the result type void as a special case of functions looking like traditional procedures, there is no need to provide the feature of «procedures» separately. This prevents some bloat in the language design.
Since SICP is mentioned, it is also worth noting that in the Scheme language specified by R n RS, a procedure may or may not have to return the result of the computation. This is the union of the traditional «function» (returning the result) and «procedure» (returning nothing), essentially same to the «function» concept of many ALGOL-like languages (and actually sharing even more guarantees like applicative evaluations of the operands before the call). However, old-fashion differences still occur even in normative documents like SRFI-96.
I don’t know much about the exact reasons behind the divergence, but as I have experienced, it seems that language designers will be happier without specification bloat nowadays. That is, «procedure» as a standalone feature is unnecessary. Techniques like void type is already sufficient to mark the use where side effects should be emphasized. This is also more natural to users having experiences on C-like languages, which are popular more than a few decades. Moreover, it avoids the embarrassment in cases like R n RS where «procedures» are actually «functions» in the broader sense.
In theory, a function can be specified with a specified unit type as the type of the function call result to indicate that result is special. This distinguishes the traditional procedures (where the result of a call is uninterested) from others. There are different styles in the design of a language:
- As in R n RS, just marking the uninterested results as «unspecified» value (of unspecified type, if the language has to mention it) and it is sufficient to be ignored.
- Specifying the uninterested result as the value of a dedicated unit type (e.g. Kernel’s #inert ) also works.
- When that type is a further a bottom type, it can be (hopefully) statically verified and prevented used as a type of expression. The void type in ALGOL-like languages is exactly an example of this technique. ISO C11’s _Noreturn is a similar but more subtle one in this kind.
Further reading
As the traditional concept derived from math, there are tons of black magic most people do not bother to know. Strictly speaking, you won’t be likely get the whole things clear as per your math books. CS books might not provide much help, either.
Разница между процедурой и функцией в программировании
Пользователи, далекие от программирования в принципе, сталкиваются с понятиями функции и процедуры редко, и ассоциируются они с чем-то математическим и бюрократическо-медицинским. В программировании же этими понятиями оперирует множество языков, правда, даже специалисты порой не могут четко осознать разницу между функцией и процедурой. Как с тем сусликом: он есть, но его никто не видит. Посмотрим, настолько ли невидимы отличия.
Определение
Функция в программировании — подпрограмма, вызываемая из других подпрограмм необходимое число раз.
Процедура — поименованная часть программы (подпрограмма), многократно вызываемая из последующих частей программы необходимое число раз.
Сравнение
Основная разница между функцией и процедурой — в возвращаемом результате. По сути, и функции, и процедуры представляют собой логически неделимые блоки, из которых складывается код программы. Функция возвращает значение, процедура в большинстве языков программирования — нет, либо (в Си, например) возвращает пустое значение. В последнем случае (в Си) процедура считается подчиненной разновидностью функции.

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