ISO C Void * and Function Pointers

后端 未结 3 1978
情话喂你
情话喂你 2021-02-04 02:21

While following some tutorials and reading about function pointers I learned that evidently assigning a void pointer to a function pointer in ISO C is undefined, is there any wa

相关标签:
3条回答
  • 2021-02-04 02:59

    I encountered this problem using glib. Glib data structures, such as GSList usually have a field called void *data. I wanted to store functions in a list and got a bunch of errors similar to this:

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

    This example generates a bunch of warnings using 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;
    }
    

    So I wrapped the function in a struct and all the warnings go away:

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

    It's arguable that this is quite a bit of extra code to make a few warnings disappear, but I don't like my code to generate warnings. Also, the above are toy examples. In the real code I'm writing, it turns out to be quite useful to wrap the list of functions in a struct.

    I'd be interested to hear if this is problematic or if there's a better way of doing it.

    0 讨论(0)
  • 2021-02-04 03:02

    No. The compiler is right, and you too: in C89 and C99, you can't convert between data pointers (which void * is) and function pointers, so the only way for resolving the warning is returning a function pointer from the function.

    (Note, however, that in practice this works despite the warning, and even there's this inconsistency in the standard library - the dlsym() function is used for obtaining function pointers, but it returns void * - so essentially you can ignore the warning. It will work, although strictly speaking the behavior is undefined here.)

    0 讨论(0)
  • 2021-02-04 03:21

    In tlpi-book I found this trick very interesting:

    #include <dlfcn.h>
    
    int
    main(int argc, char *argv[])
    {
        ...
        void (*funcp)(void);        /* Pointer to function with no arguments */
        ...
        *(void **) (&funcp) = dlsym(libHandle, argv[2]);
    }
    
    0 讨论(0)
提交回复
热议问题