В ANSI C вам не нужно объявлять прототип функции; тем не менее, рекомендуется использовать их. Единственная причина, по которой стандарт позволяет вам их не использовать, заключается в обратной совместимости с очень старым кодом.
Если у вас нет прототипа и вы вызываете функцию, компилятор выведет прототип из параметров, которые вы передаете в функцию. Если вы позже объявите функцию в том же модуле компиляции, вы получите ошибку компиляции, если сигнатура функции отличается от того, что угадал компилятор.
Хуже того, если функция находится в другом модуле компиляции, нет способа получить ошибку компиляции, поскольку без прототипа нет способа проверить. В этом случае, если компилятор ошибается, вы можете получить неопределенное поведение, если вызов функции помещает в стек другие типы, чем ожидает функция.
Соглашение состоит в том, чтобы всегда объявлять прототип в заголовочном файле, имя которого совпадает с именем исходного файла, содержащего функцию.
С помощью прототипов компилятор может проверить, правильно ли вы вызываете функцию (используя правильный номер и тип параметров).
Без прототипов возможно иметь это:
// file1.c
void doit(double d)
{
....
}
int sum(int a, int b, int c)
{
return a + b + c;
}
и это:
// file2.c
// In C, this is just a declaration and not a prototype
void doit();
int sum();
int main(int argc, char *argv[])
{
char idea[] = "use prototypes!";
// without the prototype, the compiler will pass a char *
// to a function that expects a double
doit(idea);
// and here without a prototype the compiler allows you to
// call a function that is expecting three argument with just
// one argument (in the calling function, args b and c will be
// random junk)
return sum(argc);
}