在函数指针用法中分配了不兼容的指针类型

时间:2018-07-02 16:30:43

标签: c casting

我正在尝试在代码中使用函数指针,代码如下。

#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”具有完全相同的类型,所以我想知道为什么会出现警告消息。有人对此有想法吗?

3 个答案:

答案 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