Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Подбельский Фомин_Программирование на языке СИ_...doc
Скачиваний:
356
Добавлен:
10.08.2019
Размер:
53.81 Mб
Скачать

Описание функции и ее тип.

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

тип имя_функции (спецификация_параметров);

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

При старом формате определения функции используется старомодный способ описания функции, не содержащий спецификации параметров:

тип имя_функции ( );

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

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

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

Тип функции f( ) - это функция, возвращающая значения типа double и имеющая параметры типов int и float. Тип функции w( ) (вводимый старомодным описанием) опознать практически невозможно. Служебное слово void определяет только тип возвращаемого значения. Таким образом, w() - это функция, не возвращающая значения и имеющая неизвестное количество параметров неизвестного типа. Именно поэтому при определении типа "функция" нужно всегда использовать прототип, а не старомодное описание.

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

Вызов функции. Для обращения к функции используется выражение с операцией "круглые скобки":

обозначение_функции (список_фактических_параметров)

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

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

Между формальными и фактическими параметрами должно быть соответствие по типам. Лучше всего, когда тип фактического параметра совпадает с типом формального параметра. В противном случае компилятор автоматически добавляет команды преобразования типов, что возможно только в том случае, если такое приведение типов допустимо. Например, пусть определена функция с прототипом:

Далее в программе использован вызов:

Оба фактических параметра в этом вызове имеют тип double. Компилятор, ориентируясь на прототип функции, автоматически предусмотрит такие преобразования:

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

всегда возвращает значение типа float. В выражения, помещенные в операторы return, компилятор автоматически добавит средства для приведения типов, т.е. получим (невидимые программисту) операторы:

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

Передача параметров по значению предусматривает следующие шаги:

1. При компиляции функции (точнее, при подготовке к ее выполнению) выделяются участки памяти для формальных параметров, т.е. формальные параметры оказываются внутренними объектами функции. При этом для параметров типа float формируются объекты типа double, а для параметров типов char и short int создаются объекты типа int. Если параметром является массив, то формируется указатель на начало этого массива и он служит представлением массива-параметра в теле функции.

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

3. Значения выражений - фактических параметров заносятся в участки памяти, выделенные для формальных параметров функции. При этом float преобразуется в double, a char и short int - в тип int (см. п. 1).

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

5. Никакого влияния на фактические параметры (на их значения) функция не оказывает.

6. После выхода из функции освобождается память, выделенная для ее формальных параметров.

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

имя_фукции (список_фактических_параметров);

Например, следующая функция возвращает значение типа void:

Обращение к ней

приведет к такому выводу на экран:

Может оказаться полезной и функция, которая не только не возвращает никакого значения (имеет возвращаемое значение типа void), но и не имеет параметров. Например, такая:

При обращении

в результате выполнения функции будет выведено на экран дисплея сообщение: