Это зависит от того, что вы подразумеваете под «действительно соответствием стандартам». Тем не менее, короткий ответ: «Хорошая идея - убедиться, что все функции имеют прототип в области видимости перед использованием».
В более квалифицированном ответе отмечается, что если функция принимает переменные аргументы (особенно семейство функций printf()
), то прототип должен находиться в области видимости, чтобы строго соответствовать стандартам. Это верно для C89 (из ANSI) и C90 (из ISO; так же, как C89, за исключением нумерации разделов). Однако, кроме функций 'varargs', функции, которые возвращают int
, не должны быть объявлены, а функции, которые возвращают что-то отличное от int
, нуждаются в объявлении, которое показывает возвращаемый тип, но не нуждается в прототипе список аргументов.
Обратите внимание, однако, что если функция принимает аргументы, которые подлежат «нормальному продвижению» в отсутствие прототипов (например, функция, которая принимает char
или short
- оба из них преобразуются в int
; более серьезно, возможно, функция, которая принимает float
вместо double
), тогда нужен прототип. Стандарт был довольно слабым, чтобы позволить старому коду на C компилироваться под стандартные совместимые компиляторы; старый код не был написан, чтобы беспокоиться о том, чтобы функции были объявлены перед использованием - и по определению, старый код не использовал прототипы, так как они не стали доступны в C, пока не появился стандарт.
C99 запрещает «неявное int» ... это означает как странные случаи, такие как «static a;
» (по умолчанию int
), так и неявные объявления функций. Они упомянуты (наряду с примерно 50 другими важными изменениями) в предисловии к ИСО / МЭК 9899: 1999,
который сравнивает этот стандарт с предыдущими версиями:
- удалить неявное
int
…
- удалить неявное объявление функции
В ISO / IEC 9899: 1990, §6.3.2.2 Функциональные вызовы указано:
Если выражение, которое предшествует списку аргументов в скобках в вызове функции, состоит из
только идентификатора, и если для этого идентификатора не видно никакого объявления, идентификатор неявно
объявляется точно так, как будто в самом внутреннем блоке, содержащем вызов функции, объявление:
extern int identifier();
появился. 38
38 То есть идентификатор с областью действия блока, объявленный как имеющий внешнюю связь с функцией типа без
информация о параметрах и возвращение int
. Если на самом деле оно не определено как имеющее функцию типа «
возвращая int
, ”поведение не определено.
Этот абзац отсутствует в стандарте 1999 года. Я (пока) не отслеживал изменение словоблудия, которое позволяет static a;
в C90 и запрещает его (требующий static int a;
) в C99.
Обратите внимание, что если функция является статической, она может быть определена до того, как ее использовать, и ей не обязательно должно предшествовать объявление. GCC можно убедить, что нестатическая функция определена без объявления перед ней (-Wmissing-prototypes
).