具有void和non-void指针参数的函数指针之间的转换 [英] Conversion between function pointers with void and non-void pointer parameters
问题描述
我有一个与空指针转换有关的问题.我的问题不是在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;
}
就是这样,程序由main
和module
两部分组成. 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屋!