Две формы не эквивалентны.
void (*ptr_foo)
вообще не является указателем на функцию.Это обычный, нефункциональный указатель void.Скобки излишни и вводят в заблуждение.Это так же, как если бы вы написали void* ptr_foo
.
void (*ptr_foo)(int, int)
- это правильный способ объявить указатель на функцию, которая принимает два int
s и возвращает void
.
Единственная причина, по которой это работает, заключается в том, что в Cvoid
указатели неявно преобразуются в любой другой тип указателя.То есть вы можете назначить любой другой указатель на void*
, и вы можете назначить void*
любому другому указателю.
Но тот факт, что это работает в этом примере, по сути является случайностью синтаксиса.Обычно вы не можете заменить void (*foo)(int, int)
на void (*foo)
.
Если вы попытаетесь сделать это с some_function
в списке аргументов для foo_for_foo
, ваш компилятор будет жаловаться при попытке вызвать some_function
, поскольку он не является указателем на функцию.
Аналогично, если ваша функция foo
вернула int
вместо void
, вы сразу заметите проблему.Объявление ptr_foo
как int (*ptr_foo)
привело бы к ошибке в операторе ptr_foo = &foo
, поскольку в отличие от void
указатели, int
указатели неявно не конвертируются в другие типы указателей.
Короче говоря, всегда используйте вторую форму .Это единственное, что является правильным в целом, несмотря на этот случай.