关于C#:不兼容的指针类型分配函数指针的用法

incompatible pointer type assigning in function pointer usage

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#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
"
, 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
"
);

    return 0;
}

使用" gcc -Wall xxx.c -o xxx -lpthread"编译代码后,编译器将显示以下消息:

func_ptr_test.c:30:16:警告:不兼容的指针类型从'PFUNC(int)'分配给'PFUNC'(aka'void()(int)')(aka'void((int))(int)'[ -Wincompatible-pointer-types] info.callback = callback_print;

但是,如果我将代码从

1
info.callback = callback_print;

1
info.callback = (PFUNC)callback_print;

不再显示警告消息。 但是,即使没有类型转换,我也认为" info.callback"与" callback_print"具有完全相同的类型,因此我想知道为什么会出现警告消息。 有人对此有想法吗?


有时,探索表面之下的内容有助于更好地理解图片。

在C语言中,您几乎可以将函数名称视为指向该函数的指针。看下面的例子

1
2
3
4
5
6
7
#include <stdio.h>

int main() {
    (*printf)("test
"
);
    return 0;
}

在上面的代码片段中,我们可以简单地使用printf()代替(*printf)(),这实际上是调用函数的常用方法。

另一个例子是signal()库函数(是的,我是FreeBSD用户),其定义为

1
2
 void
 (*signal(int sig, void (*func)(int)))(int);

调用signal()时,约定为

1
2
3
4
5
6
7
8
9
10
11
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参数。

所以,你应该有

1
2
3
4
5
void callback_print(int index) /* now you have a void ()(int) */
{
    printf("[callback] index = %d
"
, index);
}

info.callback = callback_print;执行的分配的左值匹配。


您不能使用函数指针typedef定义函数。您只需要定义函数以匹配typedef:

1
2
3
4
5
void callback_print(int index)
{
    printf("[callback] index = %d
"
, index);
}