skip to Main Content

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


  1. 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:

    void g();
    
    int main()
    {
        g(10);
    }
    
    void g(int) { ..... }
    

    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 type float.

    Login or Signup to reply.
  2. The type of the function pointer foo:

    void (*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 of void (assuming no parameters are subject to promotion, i.e. char, short, float) is compatible with foo and can be assigned to it.

    If you instead defined it like this:

    void (*foo)(void)
    

    This would generate an error for an incompatible pointer type, as foo points to a function that takes no arguments and returns void, and f does not match that.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search