我正在尝试在代码中使用函数指针,代码如下。
#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;
}
在使用“ gcc -Wall xxx.c -o xxx -lpthread”编译代码后,编译器将显示以下消息:
func_ptr_test.c:30:16:警告:不兼容的指针类型从'PFUNC(int)'分配给'PFUNC'(aka'void()(int)')(又名'void((int))(int)'[-Wincompatible-pointer-types] info.callback = callback_print;
但是,如果我将代码更改为
info.callback = callback_print;
到
info.callback = (PFUNC)callback_print;
不再显示警告消息。但是,即使没有类型转换,我也认为“ info.callback”与“ callback_print”具有完全相同的类型,所以我想知道为什么会出现警告消息。有人对此有想法吗?
答案 0 :(得分:3)
您不能使用函数指针typedef定义函数。您只需要定义函数以匹配typedef:
void callback_print(int index)
{
printf("[callback] index = %d\n", index);
}
答案 1 :(得分:3)
有时候,探索表面之下的内容有助于更好地理解图片。
在C语言中,您几乎可以将函数名称视为指向该函数的指针。看下面的例子
#include <stdio.h>
int main() {
(*printf)("test\n");
return 0;
}
在上面的代码段中,我们可以简单地使用printf()
而不是(*printf)()
,这实际上是调用函数的常用方法。
另一个例子是signal() library function(是的,我是FreeBSD用户),其定义为
void
(*signal(int sig, void (*func)(int)))(int);
致电signal()
时,约定为
void
handle(int sig)
{
...
}
int main(int argc, char **argv)
{
(void) signal(SIGUSR1, handle);
...
}
现在,您能在这里看到窍门吗?尽管signal()
被声明为接受void (*func)(int)
(即指向返回空值并接受单个int参数的函数的指针),但我们传递了该类型的函数的名称作为signal()
的第二个参数。
回到您的问题,PFUNC
是一个指向函数的别名,该函数返回void并接受单个int参数。通过将callback
声明为PFUNC callback
,您是在向编译器说明,callback
变量将指向一个函数,该函数返回void并采用单个int参数。
所以,你应该拥有
void callback_print(int index) /* now you have a void ()(int) */
{
printf("[callback] index = %d\n", index);
}
与info.callback = callback_print;
执行的分配的左值匹配。
答案 2 :(得分:0)
您对函数指针的理解有误。
你可以改变你的
PFUNC callback_print(int index)
原型为
void callback_print(int index)
一切都应该没问题。为什么编译器不高兴是因为
PFUNC callback_print(int index)
原型是 void (* (*)(int))(int)
但 PFUNC 类型是 void(*)(int)
所以你的返回类型是 void(*)(int)
而不是 void