Поведение компилятора C со старыми функциями без прототипов

StackOverflow https://stackoverflow.com/questions/2287164

Вопрос

Когда моя программа состоит из двух файлов:

главный.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

функция.c

double f(int a) {
 return 1;
}

компилятор не показывает никаких ошибок.

Когда моя программа состоит только из одного файла:

главный.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

double f(int a) {
 return 1;
}

Компилятор Visual C ++ 2008 выдает следующую ошибку:

Error 2 error C2371: 'f' : redefinition; different basic types d:\temp\projects\function1\function1\1.c 8 function1

Кто-нибудь может объяснить это странное поведение?

Это было полезно?

Решение

Обе программы неверны.

Без прототипа в области видимости компилятор предполагает, что функция возвращает 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() в другой единице перевода или нет.Они отвергают вторую программу , потому что они знать что ты этого не делаешь.

Другие советы

C будет предполагать, что функция имеет прототип int func();если вы не сказали иначе.(Обратите внимание, что в C int func();и int func(пустота);это разные вещи)

Во втором случае вы обращаетесь к f() для которого компилятор не видел никакого прототипа, поэтому он предполагает, что это int f(); .Позже он увидит ваше определение для f() который имеет другой прототип - и выдает ошибку.

Этого не происходит в 1.случае, поскольку они находятся в разных единицах компиляции.

Ваш первый пример никогда не использует func.c так что я не уверен точно, что делает компилятор для f() потому что у него нет определения.

Во втором примере я не знаю, почему у вас не может быть двух функций с разными сигнатурами, но вы вызываете не ту функцию, которую вы определили.Ты звонишь f() без каких-либо аргументов, но f ваше определение принимает значение int, что делает его другой функцией.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top