C 2018 6.7.6.3 15 сообщает, совместимы ли два типа. Так что его можно использовать для сравнения двух объявлений. Для foo
у вас есть:
int foo ();int foo (int a, int b) {...}
Из них второй имеет список параметров, а первый задается объявлением функции, которое не является частью определения функции и содержитпустой список идентификаторов. Таким образом, правило 6.7.6.3 15 применяется. В нем говорится, что список параметров не должен иметь терминатора с многоточием (и он не имеет), и что тип каждого параметра должен быть совместим с типом, который является результатом повышений аргументов по умолчанию (и они есть, поскольку int
производит int
).
Тогда для bar
имеем:
float bar();
float bar(float b, float c) {...}
Опять же, 6.7.6.3 15 применяется. Но в этом случае каждый параметр имеет тип, который не является результатом повышений аргументов по умолчанию, так как стандартные преобразования преобразуют float
в double
. Таким образом, эти два объявления объявляют bar
с несовместимыми типами.
Относительно 6.5.2.2 6:
… Если число аргументов не равно количеству параметров, поведениеundefined…
Это относится к числу параметров фактической функции, а не к числу параметров, появляющихся в (пустом) списке в объявлении.
В любом случаеправила выглядят довольно странно и неестественно. Какова была причина этого? Я полагаю, что существует некоторая обратная совместимость с предыдущими версиями Стандарта ...?
Да, C изначально был слаб в объявлениях функций, что позволяло объявлять функции с пустыми списками параметров, если я правильно помню, всеаргументы были переданы с повышенными типами. Поддержка более строгих и более точных объявлений появилась позже, и правила написаны так, чтобы старый код продолжал работать.
Обратите внимание, что правило о совместимости типов функций относится к объявлениям функций, но невызовы.
Когда вызов функции анализируется компилятором, правила в 6.5.2.2 используются для подготовки вызова. Эти правила говорят, что аргументы обрабатываются по-разному в соответствии с объявлением функции, которая видна в точке вызова. (Технически, к типу выражения, которое обозначает вызываемую функцию. Это часто имя функции, но может быть указателем на функцию, включая указатель, вычисляемый выражением приведения.)
Правила о совместимости гарантируютЕсли вы вызываете функцию, используя тип, совместимый с типом фактического определения функции, то вызов имеет определенное поведение.