I'm trying to use function pointer in my code, the code is as below.
#include <stdio.h>
#include <pthread.h>
typedef void (*PFUNC)(int);
typedef struct tag_FUNC_INFO_S
{
PFUNC callback;
int index;
} FUNC_INFO_S;
PFUNC callback_print(int index)
{
printf("[callback] index = %d\n", index);
return NULL;
}
void thread_test(FUNC_INFO_S *info)
{
info->callback(info->index);
pthread_exit(NULL);
}
int main()
{
pthread_t tid;
FUNC_INFO_S info;
info.callback = callback_print;
info.index = 777;
pthread_create(&tid, NULL, (void *)thread_test, &info);
printf("main printing\n");
return 0;
}
After compiled the code with "gcc -Wall xxx.c -o xxx -lpthread", the compiler complains with the following message:
func_ptr_test.c:30:16: warning: incompatible pointer types assigning to 'PFUNC' (aka 'void ()(int)') from 'PFUNC (int)' (aka 'void ((int))(int)' [-Wincompatible-pointer-types] info.callback = callback_print;
But, if I change the code from
info.callback = callback_print;
to
info.callback = (PFUNC)callback_print;
No warning message comes out any more. But, even without type casting, I think the "info.callback" has totally the same type with "callback_print", so I'm wondering why the warning message comes out. Does anyone have idea about this?
Sometimes, exploring what is beneath the surface helps to understand the picture better.
In C, you can pretty much treat the function name as a pointer to that function. Take a look at the example below
#include <stdio.h>
int main() {
(*printf)("test\n");
return 0;
}
In the code snippet above, we could simply use printf()
instead of (*printf)()
, and it actually is the usual way you would call a function.
Another example is the signal() library function (yes, I am a FreeBSD user), whose definition is given as
void
(*signal(int sig, void (*func)(int)))(int);
When you call signal()
, the convention is
void
handle(int sig)
{
...
}
int main(int argc, char **argv)
{
(void) signal(SIGUSR1, handle);
...
}
Now, can you see the trick here? Although, signal()
is declared to take void (*func)(int)
(i.e. a pointer to a function returning void and taking a single int argument), we pass the name of a function of that type as the second argument to signal()
.
Going back to your question, PFUNC
is an alias for a pointer to a function returning void and taking a single int argument. By declaring callback
as PFUNC callback
you are saying your compiler that, the callback
variable will point a function which returns void and takes a single int argument.
So, you should have
void callback_print(int index) /* now you have a void ()(int) */
{
printf("[callback] index = %d\n", index);
}
to match what is expected as the lvalue of your assignment performed by info.callback = callback_print;
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With