Рассмотрите этот код:
int main()
{
int e;
prn(e);
return 0;
}
void prn(double x,int t)
{
}
То, почему делает этот код, дает соблюдающие предупреждения и никакие ошибки?
m.c:9: warning: conflicting types for ‘prn’
m.c:5: note: previous implicit declaration of ‘prn’ was here
Разве это не должно давать "неопределенную функциональную" ошибку?
В C99 должна выдаваться ошибка необъявленная функция .
В C89 / 90 объявление функций не является обязательным. Если вызывается необъявленная функция, компилятор будет считать, что она возвращает int
, и передаст ей аргументы после того, как подвергнет их так называемому продвижению аргументов по умолчанию . Другими словами, компилятор попытается вывести , что это за функция, из фактического вызова. Если позже функция определяется иначе, чем то, что определил компилятор, поведение не определено. Обычно компиляторы будут жаловаться на это с предупреждением.
Это то, что вы наблюдаете в вашем случае. Когда компилятор видит вызов prn (e)
, он предполагает, что prn
- это функция int prn (int)
.Но позже он обнаруживает, что на самом деле это void prn (double, int)
. Несоответствие вызывает предупреждение.
В этом случае вам повезло в том смысле, что вызов необъявленной функции происходит в той же единице трансляции, где функция определена. Таким образом, компилятор имеет возможность сравнить вызов и определение и выдать предупреждение о конфликте. Если бы prn
был определен в какой-то другой единице трансляции, у компилятора никогда не было бы возможности сравнить их, так что у вас на руках было бы полноценное неопределенное поведение.
C89 имеет неявные объявления функций. Если вы используете функцию без ее объявления, компилятор предполагает, что это int prn ()
. Когда оказывается, что это неверно (поскольку типы возвращаемых данных различаются), он сообщает вам об этом.
Обратите внимание, что пустой список аргументов в объявлении функции означает «параметры не указаны», а не «без параметров». Тогда вы обязаны убедиться, что входные параметры совпадают между вызывающим и вызываемым (чего здесь нет), и вы можете вообще не получить помощи от компилятора в этом.
В C99 эта «функция» была удалена. Я думаю, что это было действительно только в C89 для совместимости с древним кодом C. Было время, когда у C вообще не было прототипов функций, вам всегда приходилось делать все самостоятельно.