23

在遵循一些教程并阅读有关函数指针的内容时,我了解到显然将 void 指针分配给 ISO C 中的函数指针是未定义的,有没有办法解决我在编译时收到的警告(例如,更好的编码方式)或我应该忽略它吗?

警告:

ISO C forbids assignment between function pointer and 'void *' [-pedantic]

示例代码:

void *(*funcPtr)();
funcPtr = GetPointer();

GetPointer 是一个返回空指针 EG 的函数

void *GetPointer();
4

3 回答 3

13

tlpi-book我发现这个技巧非常有趣:

#include <dlfcn.h>

int
main(int argc, char *argv[])
{
    ...
    void (*funcp)(void);        /* Pointer to function with no arguments */
    ...
    *(void **) (&funcp) = dlsym(libHandle, argv[2]);
}
于 2013-10-21T06:32:40.267 回答
8

不。编译器是对的,你也是:在 C89 和 C99 中,你不能在数据指针(即void *)和函数指针之间进行转换,所以解决警告的唯一方法是从函数返回一个函数指针。

(但是请注意,尽管有警告,但实际上这仍然有效,即使标准库中存在这种不一致 - 该dlsym()函数用于获取函数指针,但它返回void *- 所以基本上你可以忽略警告。它会工作,虽然严格来说,这里的行为是未定义的。)

于 2013-01-03T06:50:04.820 回答
4

我使用 glib 遇到了这个问题。Glib 数据结构,例如 GSList 通常有一个称为 void *data 的字段。我想将函数存储在一个列表中,并得到了一堆类似于此的错误:

warning: ISO C forbids passing argument 2 of ‘g_slist_append’ between function pointer and ‘void *’ [-pedantic]

此示例使用 gcc -Wall -ansi -pedantic 生成一堆警告

typedef int (* func) (int);

int mult2(int x)
{
    return x + x;
}

int main(int argc, char *argv[])
{
    GSList *functions = NULL;
    func f;

    functions = g_slist_append(functions, mult2);
    f = (func *) functions->data;
    printf("%d\n", f(10));
    return 0;
}

所以我将函数包装在一个结构中,所有警告都消失了:

struct funcstruct {
    int (* func) (int);
};

int mult2(int x)
{
    return x + x;
}

int main(int argc, char *argv[])
{
    GSList *functions = NULL;
    struct funcstruct p;
    p.func = mult2;

    functions = g_slist_append(functions, &p);
    p = * (struct funcstruct *) functions->data;
    printf("%d\n", p.func(10));
    return 0;
}

可以说这是使一些警告消失的相当多的额外代码,但我不喜欢我的代码生成警告。此外,以上是玩具示例。在我正在编写的实际代码中,将函数列表包装在结构中非常有用。

我很想知道这是否有问题,或者是否有更好的方法。

于 2013-05-07T10:34:09.290 回答