Ответ 1
Потому что стандарт (6.7.6.3p8) говорит, что
Объявление параметра как функции, возвращающей тип, должно быть настроено на указатель на функцию, возвращающую тип, как в 6.3.2.1.
Это похоже на то, как параметры массивов настраиваются на указатели (6.7.63.p7), если вы об этом думаете.
void some_func(void (void));
void some_func(void (*)(void));
являются совместимыми объявлениями, такими как:
void other_func(char string[]);
void other_func(char *string);
являются.
Обратите внимание, что корректировка не делает void some_func(void (*)(void)
совместимым с void some_other_func(void (**)(void)
или void yet_another_func(void (*****)(void)
и так далее) что касается функций, объявления на самом деле больше не отражают использование (несмотря на то, что это было намерением автора оригинального языка). В стандартизированном C из-за того, как идентификаторы функций переходят в указатели, и из-за того, что не имеет значения, используете ли вы использовать тип функции или тип указателя на функцию для вызова; вы можете вызывать любую функцию с произвольным числом *
:
#include <stdio.h>
int main()
{
(*puts)("hello world");
(******puts)("hello world");
(***&*&*puts)("hello world"); //& cancels a * as per 6.5.3.2p3
int (*p)(char const*) = puts;
int (**pp)(char const*) = &p;
int (***ppp)(char const*) = &pp;
(**ppp)("hello world"); //at least two asterisks required here
}