2
#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?

4
  • 2
    It’s not the const that causes the trouble; it's the extra layer of pointer, plus the fact that &function produces the same value as just function. Commented Mar 17 at 8:20
  • 1
    What compiler is that? If there are no copy-and-paste error in the error message it is highly misleading, because it should have said aka 'int (* const*)(int). "How can I fix it?" This depends on what you want to do, especially why you want a pointer to a function pointer, which is not something that commonly needed. Commented Mar 17 at 8:26
  • const func_t *ptr = &foo; is valid in C, but its behavior may vary depending on the compiler implementation and settings. My compiler (gcc 13.2.0, clang 17.0.6, target x86_64-unknown-linux-gnu ) gives incompatible pointer type warning but still compiles. Commented Mar 17 at 9:04
  • 1
    @xy3333 Not really. const func_t* is an object pointer type, but &foo is a function pointer type. The C standard does not say you can convert between these two. In fact they may not even be of the same size. See stackoverflow.com/a/4810460/3966456 Commented Mar 17 at 9:06

1 Answer 1

2

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;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.