ccompiler-errorsconstantsfunction-pointerstypedef

Why does this function pointer typedef behave differently when used with const?


#include <stdio.h>

typedef int (*func_t)(int);

int foo(int x) {
    return x * 2;
}



int main() {
    const func_t ptr = foo; // Works
    //const func_t *ptr = &foo; // Fails: why?
    printf("%d\n", ptr(5)); // Outputs 10
}

Issue:

The line const func_t ptr = foo; works fine.

However, uncommenting const func_t *ptr = &foo; results in a compilation error

error: invalid conversion from 'int (*)(int)' to 'const func_t*' {aka 'int (* const)(int)'}

Why does const func_t *ptr = &foo; fail, and how can I fix it?


Solution

  • This is one of the reasons why hiding pointers behind typedef isn't a good idea.

    const func_t ptr makes the function pointer "const". That is, it is equivalent to int (* const func_t)(int);.

    Functions, whenever used in expressions, "decay" into a pointer to that function. That's why ptr = foo; works, foo decays into an int (*)(int). However, just like when dealing with arrays, decay does not happen in case of &. So &foo gives a pointer to a function too.

    And you cannot assign an int (*)(int) to a pointer-to-pointer to function and const has nothing to do with that - it's simply the wrong number of redirections.

    You could however do this:

    const func_t  ptr1 = foo;
    const func_t* ptr2 = &ptr1;
    

    ptr2 is int (*const *)(int) and that's what you get if you take &ptr1.

    Best practice here is to get rid of the hidden pointer inside the typedef in the first place, since it is obviously quite confusing:

    typedef int func_t (int);
    ...
    func_t* const ptr1 = foo;