Reputation: 141523
Compiling with gcc8:
#include <stdio.h>
void some_func(void f1(void), void (*f2)(void))
{
printf("%d\n", f1);
printf("%d\n", f2);
}
Gives (only) the following warnings:
<source>:11:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void (*)(void)' [-Wformat=]
printf("%d\n", f1);
<source>:12:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void (*)(void)' [-Wformat=]
printf("%d\n", f2);
Why is the type of f1
the same as f2
? Only f2
is declared as a function pointer. I would expect f1
not to compile at all, as it names a function type, not a function pointer. What is the rule that says, that a function type inside a function parameter list changes to a pointer to that function type?
Upvotes: 16
Views: 779
Reputation: 60107
Because the standard (6.7.6.3p8) says that
A declaration of a parameter as ''function returning type'' shall be adjusted to ''pointer to function returning type'', as in 6.3.2.1.
It's similar to how arrays parameters are adjusted to pointers (6.7.63.p7) , if you think about it.
void some_func(void (void));
void some_func(void (*)(void));
are compatible declarations, just like:
void other_func(char string[]);
void other_func(char *string);
are.
Note that the adjustment doesn't make void some_func(void (*)(void)
compatible with void some_other_func(void (**)(void)
or void yet_another_func(void (*****)(void)
and that as far as functions are concerned, declarations don't really reflect use anymore, (despite that being the intention of the language's original author). In standardized C, due to how function identifiers decay to pointers and due to how it doesn't matter whether you use a function type or a function pointer type to make a call, you can call any function with arbitrarily many *
:
#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
}
Upvotes: 24
Reputation: 499
Because in C, in that case, the function name itself is a function pointer. See this answer: Why is using the function name as a function pointer equivalent to applying the address-of operator to the function name?
Upvotes: 2