Ваше предположение, что объявление не соответствует определению, неверно. (Это было бы в случае C ++, но не в C). На языке Си
double f();
Объявление
не полностью объявляет функцию, то есть не вводит прототип . Он только объявляет о том, что функция f
существует и ее тип возвращаемого значения double
. Он абсолютно ничего не говорит о количестве и типах аргументов f
s. Аргументы могут быть абсолютно любыми. В этом смысле объявление в вашем примере действительно соответствует определению (то есть оно не противоречит определению, что хорошо для компилятора C).
Если вы действительно хотите объявить функцию, которая не принимает аргументов, вам придется указать явный void
в списке параметров
double f(void);
Это действительно противоречило бы определению. То, что у вас изначально нет.
Когда вы вызываете функцию, которая была объявлена с пустым списком параметров ()
, вы несете ответственность за предоставление правильного числа аргументов соответствующего типа. Если вы допустили ошибку, поведение не определено. Об этом предупреждает компилятор, когда вы изменяете фактический тип параметра на float
.
Ваш анализ "пар" декларации и определения не совсем корректен. Это ошибочно. Дело не в декларации и определении. Это действительно определение и способ, которым вы вызываете свою функцию. В исходном случае вы вызываете его с аргументом double
, а функция объявляется с параметром double
. Так что все совпадает. Но когда вы вызываете его с аргументом double
и объявляете его с параметром float
, вы получаете несоответствие.
Также обратите внимание, что когда функция объявляется без прототипа, аргументы float
всегда переводятся в аргументы double
. По этой причине невозможно передать аргумент float
в функцию, объявленную со списком параметров ()
. Если вы хотите иметь float
аргументы, всегда используйте прототипы (то же самое относится и к char
и short
аргументам).