Декларация:
int f();
... сообщает компилятору, что некоторый идентификатор (в данном случае f
) называет функцию, и сообщает ей тип возвращаемого значения функции - но не указывает число или тип (s) параметра (ов), которые функция должна получить.
Прототип:
int f(int, char);
... в остальном аналогичен, но также указывает номер / тип параметра (ов), которые функция предназначена для приема. Если для этого не требуется параметр, вы используете что-то вроде int f(void)
, чтобы указать это (так как оставление скобок пустым является объявлением). Определение функции нового стиля:
int f(int a, char b) {
// do stuff here...
}
... также выступает в качестве прототипа.
Без прототипа в области видимости компилятор применяет продвижение по умолчанию к аргументам перед вызовом функции. Это означает, что любой char
или short
повышен до int
, а любой float
повышен до double
. Следовательно, если вы объявляете (а не создаете прототип) функцию, вы не хотите указать какой-либо параметр char
, short
или float
- вызов такой вещи будет / будет давать неопределенное поведение , С флагами по умолчанию компилятор вполне может отклонить код, поскольку в принципе нет способа его правильно использовать. Вы могли бы найти некоторый набор флагов компилятора, который заставил бы его принять код, но это было бы довольно бессмысленно, поскольку вы все равно не можете его использовать ...