#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?
#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?
1 Answer
Reset to default 2This 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;
const
that causes the trouble; it's the extra layer of pointer, plus the fact that&function
produces the same value as justfunction
. – Jonathan Leffler Commented Mar 17 at 8:20aka '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. – Weijun Zhou Commented Mar 17 at 8:26const 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. – xy3333 Commented Mar 17 at 9:04const 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/a/4810460/3966456 – Weijun Zhou Commented Mar 17 at 9:06