问题
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 way to resolve the warning I receive during compile time (e.g. a better way of coding it) or should I just ignore it?
Warning:
ISO C forbids assignment between function pointer and 'void *' [-pedantic]
Example Code:
void *(*funcPtr)();
funcPtr = GetPointer();
GetPointer is a function that returns a void pointer E.G.
void *GetPointer();
回答1:
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]);
}
回答2:
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.)
回答3:
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.
来源:https://stackoverflow.com/questions/14134245/iso-c-void-and-function-pointers