Материал: lectures_3

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Понятие параметров функции знакомо читателю по работе с библиотечными функциями.

36.3.Понятие о функции

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

Прежде всего, отметим, что в языке Си предусмотрены две категории функций:

Обычные функции.

Встроенные функции или inline функции (стандарт С99). Основное отличие между этими категориями функции состоит в том, что

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

Рассмотрим компоненты этого определения:

Имя. Каждая функция должна иметь имя, которое позволяет обратиться к инструкциям, входящих в функцию. Такое обращение называется вызовом функции. Функцию можно вызывать из другой функции.

Автономность – важнейшая характеристика функции. Язык Си обеспечивает синтаксическую независимость функции от другого программного кода.

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

помощью аппарата параметров функции, используя в качестве параметров указатели.

При работе с функциями языка Си следует различать три понятия:

Определение функции.

Объявление функции (прототип).

Вызов функции.

Определение функции является ее реализацией. Написать функцию означает написать ее определение. Каждая функция в программе должна быть представлена только одним определением (это не относится к так называемым встроенным функциям или inline функциям).

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

76

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

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

36.4.Назначение функций

Основное назначение подпрограмм и функций языка Си, в том числе состоит в следующем:

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

Подпрограммы применяются для повторного использования

кода.

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

Следует учитывать, что имеются и негативные последствия применения функций. Они связаны с временными накладными расходами, с которыми связано применение функций. Это положение характерно для обычных функций. Для inline функций временные накладные расходы отсутствуют. Особенно следует обращать внимание на этот фактор в том случае, когда функция вызывается в цикле.

36.5.Определение функции

Внекоторых языках, например в языке Паскаль, различают две вида подпрограмм:

Подпрограммы – процедуры.

77

Подпрограммы – функции.

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

Функции, возвращающие значение.

Функции, не возвращающие значение.

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

Прежде всего, следует различать старый и новый стиль организации функций. Старый стиль организации функций связывают с именами авторов классической книги по языку Си: Кернигана и Ритчи (стиль K&R). Новый стиль – это стиль, принятый в стандарте языка Си. В настоящее время при разработке новых программ старый стиль организации функций практически не используется. Учитывая это обстоятельство, основное внимание уделим новому стилю организации функций.

Определение функции состоит из двух структурных частей: заголовок и

тело. Формально это можно представить следующим образом:

Заголовок_функции

{

определения, объявления и инструкции

}

Заголовок функции определяет ее интерфейс с внешним миром (клиентским кодом), а ее тело - алгоритм, который она реализует. Все элементы, расположенные до открывающей фигурной скобки, составляют заголовок функции. Телом функции является блок.

Заголовок функции имеет следующую структуру:

тип имя([определения_формальных_параметров ])

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

Второй элемент заголовка функции имя является ее именем, которое используется для идентификации ее как функции.

Третий элемент заголовка определения_формальных_параметров ,

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

78

Замечание. Стандарт С89 поддерживал так называемый принцип неявного int. В соответствии с этим принципом при отсутствии спецификатора типа по умолчанию предполагает использовании типа int. Стандарт C99 не рекомендует придерживаться этого принципа.

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

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

должно содержать инструкцию return, имеющую следующий формат return выражение;

Инструкция return, рассматриваемого вида, выполняет два действия:

1.Вычисляет значение своего компонента выражение, формирующего значение, возвращаемое функцией.

2.Прекращает вычисления, выполняемые в теле функции, и возвращает управление клиентскому коду.

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

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

В качестве примера функции, возвращающей значение, приведем заголовок стандартной функции, предназначенной для возведения величины x в степень y:

double pow(double x, double y)

Заметим, что недопустимо написать заголовок функции pow() в

следующем виде:

double pow(double x,y) /* Синтаксическая ошибка */

Функция pow принимает два аргумента, имеющих тип double, и возвращает в точку ее вызова значение типа double.

Приведем еще один пример заголовка функции: void table(double xn, double xk, int n)

79

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

Телом любой функции, является блок. Блоком называется последовательность инструкций, заключенная в фигурные скобки. Тело функции может содержать вложенные блоки. В блоке могут встречаться инструкции двух видов: инструкции объявления и выполняемые инструкции. В стандарте C89 в блоке вначале следует располагать инструкции объявления, а затем выполняемые инструкции. В стандарте C99 это ограничение отсутствует, и инструкции объявления могут располагаться в любом месте блока. Используя эту возможность, можно располагать определение переменной в той точке программы, где она начинает использоваться. Это повышает читабельность программы.

Рассмотрим два примера определений функций пользователя. В первом из них функция имеет возвращаемое значение, а вторая не имеет возвращаемого значения.

Пример 1. Приведенная ниже функция (max2()) принимает два аргумента вещественного типа и возвращает значение набольшего из своих аргументов.

double max2(double a, double b)

{

double max; if(a > b)

max = a; else

max = b; return max;

}

В функции max2() результат вычислений фиксируется с помощью локальной переменной max. Приведем альтернативный вариант функции, решающей ту же задачу, что функция max2().

double max2_2(double a, double b)

{

if(a > b) return a;

return b;

}

Сравним два варианта решения. Второй вариант (функция max2_2()) выглядит более компактной. Некоторые программиста возможно в качестве недостатка отметили бы наличие в теле этой функции двух инструкций return. Это можно рассматривать как нарушение принципа одного входа и одного выхода. Действительно лучше придерживаться принципа, в соответствии с которым функция имеет только одну точку выхода. Это

80

Источник: https://studfile.net/preview/16544272/