Одной из наиболее важных особенностей ANSI Си являются прототипы функций. Прототип функции сообщает компилятору тип данных, возвращаемых функцией, число параметров, получаемых функцией, тип и порядок следования параметров. Компилятор использует прототипы функций для проверки корректности обращений к функции. Предыдущие версии Си не выполняли этот вид проверки, так что существовала возможность неправильного вызова функции, при котором компилятор не регистрировал ошибки. Такие обращения могли приводить к фатальным ошибкам при выполнении программы, или к ошибкам, которые, не вызывая краха программы, приводили тем не менее к трудно обнаруживаемым логическим ошибкам. Прототипы функций в ANSI Си исправляют такое положение дел.
Прототипом функциив общем виде:
тип_возвращаемого_значения имя_функции (список абстрактных типов);
Пример объявления прототипа функции, вычисляющей максимальное значение из трёх целочисленных значений.
int maximum (int, int, int);
Этот прототип объявляет, что maximum получает три параметра типа int и возвращает результат типа int. Обратите внимание, что прототип функции имеет тот же вид, что и первая строка определения функции maximum,за исключением того, что в него не включены имена параметров (х, у и z).
|
|
Имена параметров иногда включаются в прототип функции с целью документирования. Компилятор игнорирует эти имена. Пропуск точки с запятой в конце прототипа функции вызывает синтаксическую ошибку. Вызов функции, который не соответствует ее прототипу, вызывает синтаксическую ошибку. Ошибка генерируется также в том случае, если не согласованы прототип и определение функции. Например, если прототип функции записать в виде:
void maximum(int, int, int);
то компилятор зарегистрировал бы ошибку, поскольку возврат типа void в прототипе функции отличался бы от возврата типа int заголовка функции.
Другое важное следствие применения прототипов функций – автоматическое приведение аргументов, т.е. принудительное преобразование аргументов функции к соответствующему типу. Преобразование значений к более высоким типам происходит автоматически. Преобразование значений к более низким типам обычно приводит к неверному результату. Следовательно, значение может быть преобразовано в более низкий тип только посредством явного присваивания переменной более низкого типа или с помощью операции приведения. Значения аргументов функции преобразуются к типу параметров прототипа функции таким образом, как будто они непосредственно присваиваются переменным этого типа. Если прототип для данной функции не был включен в программу, компилятор формирует собственный прототип функции, используя ее первое вхождение в программу: или определение, или обращение к функции. По умолчанию компилятор предполагает, что функция возвращает тип int, ничего не предполагая относительно типа аргументов. Следовательно, если аргументы, переданные функции, некорректны, то компилятор не обнаружит ошибку.
|
|
Пропуск прототипа функции вызывает синтаксическую ошибку, если функция возвращает тип, отличный от int,а определение функции появляется в программе после вызова функции. В других случаях пропуск прототипа функции может вызвать ошибку во время выполнения программы или привести к непредвиденному результату. Прототип функции, размещенный вне любого определения функции, применяется ко всем вызовам, появляющимся в файле после прототипа функции. Прототип функции, помещенный в функцию, применяется только к тем вызовам, которые делаются из этой функции.