Обе программы неверны.
Без прототипа в области видимости компилятор предполагает, что функция возвращает int
и принимает неопределенное количество параметров.
Давайте немного изменим ваши файлы:
$ cat func.c
double f(int a) {
return 1.0;
}
$ cat main.c
#include <stdio.h>
int main(void) {
double d = f();
printf("%lf\n", d);
return 0;
}
Когда я его компилирую, gcc предупреждает меня (Visual C ++ должен тоже в режиме соответствия). Но давайте проигнорируем предупреждение.
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
func.c:1: warning: unused parameter 'a'
main.c: In function 'main':
main.c:4: warning: implicit declaration of function 'f'
$ ./test
0.000000
Он не печатал 1, но печатал 0. Это потому, что компилятор предполагал, что f()
вернул int
, а присвоение d = f();
преобразовало это "int
" в double
. Компилятор все еще компилировал код, потому что он не мог сказать, что f()
не был определен так, как это было (неявно) объявлено. Но компиляция вышеуказанной программы не требуется стандартом, поэтому компилятор мог ее отклонить (например, попробуйте gcc -Werror
!)
Если у нас все в одном файле:
$ cat func.c >>main.c
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
main.c:4: warning: implicit declaration of function 'f'
main.c: At top level:
main.c:9: error: conflicting types for 'f'
main.c:4: error: previous implicit declaration of 'f' was here
main.c:9: warning: unused parameter 'a'
Теперь компилятор видит конфликт и выдает сообщение об ошибке. Но компилятор не обязан отклонять вышеуказанную программу, он может или не может.
Большинство компиляторов не отклоняют первую программу, потому что они не знают, есть ли у вас правильное определение функции f()
в другой единице перевода или нет. Они отвергают вторую программу, потому что они знают , что вы не знаете.