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

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

main.c

#include <stdio.h>

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

func.c

double f(int a) {
 return 1;
}

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

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

main.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

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

5
задан Art Spasky 18 February 2010 в 08:21
поделиться

3 ответа

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

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

5
ответ дан 13 December 2019 в 19:26
поделиться

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

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

0
ответ дан 13 December 2019 в 19:26
поделиться

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

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

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

6
ответ дан 13 December 2019 в 19:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: