I’m trying to make sure I understand the syntax for function pointers in C. I know it’s just a pointer to a specific type. That being said, why does the following code compile and print ’10’?
(Note I’m using GCC 9.4.0 on Ubuntu 20.04)
void f(int);
void (*foo)() = f;
int main(){
foo(10);
return 0;
}
void f(int n){
printf("%dn", n);
}
Shouldn’t we at least get a compile time warning: initialization of ‘void(*)()’ with incompatible pointer type ‘void(*)(int)’? Is foo getting initialized to void(*)(int) based on f?
If I change ‘void f(int)’ to ‘void f(float)’ I do get a warning. If I add 3 more int params to f e.g. void f(int, int, int, int) it still compiles and runs fine. If I make the last param a float, another warning.
2
Answers
The rules are the same for function pointer declarations as for function declarations ; and a pointer to function with empty parentheses parameter list is compatible with a pointer to prototyped function, if the return type matches.
In your example the issues are equivalent to:
The rules are: you can declare a function with empty parentheses and call it with arguments, but in the function call, certain conditions must be met and it is undefined behaviour with no diagnostic required if those conditions are not met.
One of the "certain conditions" is that you cannot have
float
as a parameter type in the function definition. Another is that the type and count of arguments must match the type and count of parameters in the function definition. To repeat, no diagnostic is required for any of this; your compiler is going above minimum requirements by warning about the incorrect parameter typefloat
.The type of the function pointer
foo
:Is a pointer to a function taking an unspecified number of parameters and returning
void
. So a pointer to any function that has a return type ofvoid
(assuming no parameters are subject to promotion, i.e.char
,short
,float
) is compatible withfoo
and can be assigned to it.If you instead defined it like this:
This would generate an error for an incompatible pointer type, as
foo
points to a function that takes no arguments and returnsvoid
, andf
does not match that.