繁体   English   中英

ISO C Void *和功能指针

[英]ISO C Void * and Function Pointers

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

警告:

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

示例代码:

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

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

void *GetPointer();

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]);
}

编号是正确的,您也是:在C89和C99中,您无法在数据指针( void * is)和函数指针之间进行转换,因此解决警告的唯一方法是从函数返回一个函数指针。

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

我使用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;
}

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

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

基于@WeinanLi答案,但为了清晰起见使用辅助功能:

#include <dlfcn.h>

/* Pointer to function with no arguments */
typedef void (*functor_t)(void);

void load_symbol( functor_t* functor, void* dl_handle, const char* symbol_name ) {
    *(void**)functor = dlsym( dl_handle, symbol_name );
}

int
main(int argc, char *argv[])
{
    // [...]
    functor_t funcp;
    // [...]
    load_symbol( &funcp, libHandle, argv[2]);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM