Conversion between function pointers with void and non-void pointer parameters

自闭症网瘾萝莉.ら 提交于 2019-12-12 18:15:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!