В языке C прототипы функций (function prototypes) — это объявления функций, которые информируют компилятор о возвращаемом типе, имени и типах параметров функции до её фактической реализации. Прототипы обычно располагаются в заголовочных файлах (.h). Их использование позволяет:
Пример прототипа:
// math_utils.h int sum(int a, int b); // Прототип функции
// main.c #include "math_utils.h" int main() { int result = sum(3, 4); // компилятор знает о сигнатуре sum }
Без прототипа функция воспринималась бы как возвращающая int и принимающая неопределённое число аргументов, что может привести к неожиданным ошибкам времени выполнения.
Вопрос: Можно ли вызывать функцию в C до её определения, если она не объявлена как прототип?
Ответ: В стандарте C89 разрешалось вызывать функции до их определения, если возвращаемое значение — int, а параметры не проверялись (implicit int, implicit promotion). В современных стандартах это приводит к предупреждениям или ошибкам, и использовать такой подход не следует.
Пример ошибки:
int main() { foo(1, 2); // Нет прототипа foo } int foo(double x, double y) { ... }
Компилятор вызовет функцию, считая параметры за int, хотя сигнатура подразумевает double — результат: UB или неверные значения.
История
В крупном научном проекте в одном из модулей отсутствовали прототипы для функций обработки данных. При передаче
floatвместоintошибки выявились только после некорректных вычислений на этапе эксплуатации, хотя компиляция проходила без ошибок.
История
В модульной утилите автоматизации сборки функции определялись только в
.c-файлах, без объявлений в заголовках. В двух модулях были определены функции с одинаковым именем и несовместимыми параметрами — привело к трудноуловимой ошибке связывания при линковке.
История
В проекте под embedded-систему возникла проблема: функция инициализации вызывалась до её определения без прототипа. Из-за предположения компилятора о типах параметров и возврата сильно нарушалась логика и система глючила только на определённых сборках с разной организацией памяти.