I have this piece of code:
int foo(){ return 0;}
int main()
{
int (*float_function)(float) = foo;
}
When compiled using x86-64 gcc 12.2
, with -Wall
, it produces the warning (Link):
warning: initialization of 'int (*)(float)' from incompatible pointer type 'int (*)()' [-Wincompatible-pointer-types]
but when I change from float
to double
(Link):
int foo(){ return 0;}
int main()
{
int (*double_function)(double) = foo;
}
the warning is now gone.
But I think that both of these should get a warning.
Am I wrong somewhere? Why does gcc not complain on the second example?
CodePudding user response:
int foo()
is declared without specifying its parameters. This is an obsolescent feature that lets you call it with any arguments. When calling the function, integer arguments are promoted to int
(if needed), and float
arguments are promoted to double
.
Due to this, it's impossible for this function to receive a float
parameter, which makes it incompatible with int (*)(float)
, but not with int (*)(double)
.
If you want a function that takes no parameters, declare it as int foo(void)
which will make it incompatible with both.
Note that even with double
, the code is not valid C because int foo() {...}
is a function definition, so the compiler knows that it has no parameters (see chux's comment below for the standard reference). Most compilers still allow it.
If you replace it with a declaration int foo();
and place the definition elsewhere then the above is correct. In that case, the relevant standard quote (C17 6.7.6.3/15) is:
For two function types to be compatible, [...] If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, [...] the type of each parameter shall be compatible with the type that results from the application of the default argument promotions.