问题
I have a question related to void pointer conversions. Instead of casting between void* and non-void pointers, my question is about casting between function pointer types, one of which has void*
as parameter type and another has a pointer to some particular data type.
Here's the code which allows to reproduce the warning messages:
#include <stdio.h>
typedef void (*module_outputMessage)(void *param, const char *msg);
void module_function(module_outputMessage outputFunc, void *output_param, int msgid, const char *msg1, const char *msg2)
{
if (msgid == 0)
outputFunc(output_param, msg1);
else
outputFunc(output_param, msg2);
}
struct main_state
{
int msgid;
};
void main_outputMessage(struct main_state *state, const char *str)
{
printf("Message %d: %s\n", state->msgid, str);
state->msgid++;
}
int main(int argc, char *argv[])
{
struct main_state state;
const char *msg1 = "abc", *msg2 = "def";
state.msgid = 0;
module_function(&main_outputMessage, &state, 0, msg1, msg2);
module_function(&main_outputMessage, &state, 0, msg1, msg2);
module_function(&main_outputMessage, &state, 1, msg1, msg2);
module_function(&main_outputMessage, &state, 0, msg1, msg2);
module_function(&main_outputMessage, &state, 1, msg1, msg2);
return 0;
}
This is it, the program is made of two parts, main
and module
. module
outputs the text, but it shouldn't deal with all output specifics - instead, main
is the one to handle the output. Since main
is dependent on module
and not vice versa, module
does not know what's going on in main
, and to output the messages, it needs an output function to be passed as a parameter. In order for output to know which state object it's dealing with, that object needs to be passed along with the output function. And that's where conversion comes into play: module
doesn't know and shouldn't care about the implementation of main
, so instead of using struct main_state*
as function parameter, it accepts void*
which it merely passes to output function.
So it all boils down to conversion between these types:
void (*)(void* , const char*)
void (*)(struct main_state *, const char*)
The program gives the expected results:
Message 0: abc
Message 1: abc
Message 2: def
Message 3: abc
Message 4: def
However, GCC complains about incompatible pointer types (I get five messages like this, one for each function call):
funcpointvoid.c: In function ‘main’:
funcpointvoid.c:33:2: warning: passing argument 1 of ‘module_function’ from incompatible pointer type
module_function(&main_outputMessage, &state, 0, msg1, msg2);
^
funcpointvoid.c:5:6: note: expected ‘module_outputMessage’ but argument is of type ‘void (*)(struct main_state *, const char *)’
void module_function(module_outputMessage outputFunc, void *output_param, int msgid, const char *msg1, const char *msg2)
^
So even though it works fine for me, with these warnings I'm not sure if this 'architecture' can be relied upon. But as I see it myself, the only difference is pointers to void and non-void, and it's just one way to use generic pointers for whatever purpose they exist. Is this a bug of GCC or have I missed something?
回答1:
void (*)(void* , const char*)
void (*)(struct main_state *, const char*)
are two different types and as there are no implicit conversion between function pointer types you need to make the conversion explicit by using a cast:
Change:
module_function(&main_outputMessage, &state, 0, msg1, msg2);
to
module_function((module_outputMessage) main_outputMessage,
&state, 0, msg1, msg2);
but be aware that the function call outputFunc
technically invoke undefined behavior as void (*)(void* , const char*)
and void (*)(struct main_state *, const char*)
are not compatible types.
来源:https://stackoverflow.com/questions/24757510/conversion-between-function-pointers-with-void-and-non-void-pointer-parameters