具有void和non-void指针参数的函数指针之间的转换 [英] Conversion between function pointers with void and non-void pointer parameters

查看:135
本文介绍了具有void和non-void指针参数的函数指针之间的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个与空指针转换有关的问题.我的问题不是在void *和非void指针之间进行转换,而是在函数指针类型之间进行转换,其中一种类型的函数指针类型为void*,而另一种类型的指针指向某个特定数据类型.

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

就是这样,程序由mainmodule两部分组成. module输出文本,但不应处理所有输出细节-而是main是处理输出的文本.由于main依赖于module,而不是相反,因此module不知道main中发生了什么,并且要输出消息,它需要将输出函数作为参数传递.为了使输出知道它正在处理哪个状态对象,需要将该对象与输出函数一起传递.这就是转换起作用的地方:module不知道也不应该关心main的实现,因此,它接受void*而不是将struct main_state*用作函数参数,而只是将其传递给输出功能.

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

但是,GCC抱怨指针类型不兼容(我收到五条这样的消息,每个函数调用一个):

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)
      ^

因此,即使对我来说效果很好,但在收到这些警告时,我不确定是否可以依赖此体系结构".但是正如我自己所看到的,唯一的区别是指向void和non-void的指针,这只是将通用指针用于存在的任何目的的一种方法.这是GCC的错误还是我错过了什么?

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?

推荐答案

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:

更改:

module_function(&main_outputMessage, &state, 0, msg1, msg2);

module_function((module_outputMessage) main_outputMessage,
    &state, 0, msg1, msg2);

,但是请注意,函数调用outputFunc从技术上讲会调用未定义的行为,因为void (*)(void* , const char*)void (*)(struct main_state *, const char*)是不兼容的类型.

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.

这篇关于具有void和non-void指针参数的函数指针之间的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆