【发布时间】:2014-09-05 14:35:09
【问题描述】:
我有一个与 void 指针转换有关的问题。我的问题不是在 void* 和非 void 指针之间进行转换,而是关于函数指针类型之间的转换,其中一个具有 void* 作为参数类型,另一个具有指向某些特定数据类型的指针。
这是允许重现警告消息的代码:
#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 的实现,因此它不使用struct main_state* 作为函数参数,而是接受void*,它只是传递给输出函数。
所以这一切都归结为这些类型之间的转换:
void (*)(void* , const char*)
void (*)(struct main_state *, const char*)
程序给出了预期的结果:
Message 0: abc
Message 1: abc
Message 2: def
Message 3: abc
Message 4: def
但是,GCC 抱怨指针类型不兼容(我收到五条这样的消息,每个函数调用一条):
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 的错误还是我错过了什么?
【问题讨论】:
-
也许最简单的方法是将
main_outputMessage原型更改为void (void *, const char*),然后将void*参数转换为struct main_state*。 -
一个更短的代码,将重现相同的警告/错误,将
int (*pfn)(Type const*, Type const*)传递给标准库函数qsort以对Type序列进行排序。我还没有遇到一个工程师,在最初使用学习该 api 时,没有遇到同样的情况。 -
@Holt 这不仅是解决此问题的最简单方法,而且是正确的方法。+1.
标签: c gcc function-pointers void-pointers