我考虑如何正确使用void *
(我从C语言中休息一下)。我记得void *
用于启用任何参数传递给回调函数。我知道可以将原始类型int *
,const char *
或甚至值集合传递给struct attributes *
。
我考虑将指向函数的指针传递给void *
是否正常。
离。
typedef void (*callback_t)(void *);
typedef void (*my_custom_callback_t)( /* list of params */ )
void someAPIFunction( /*... */, callback_t callback, void *callback_param);
void standard_callback(void *param) {
((my_custom_callback_t) param) ( /* my params */ );
}
我考虑是否拥有这样的类型将my_custom_callback作为param传递给standard_callback是正确的吗?
void my_custom_callback(/* list of params */) { }
someAPIFunction( /*...*/, standard_callback, my_custom_callback);
答案 0 :(得分:5)
不,您不能将函数指针传递为void *
。
6.3.2.3指针
- 指向void的指针可以转换为指向任何对象类型的指针。指向的指针 任何对象类型都可以转换为指向void的指针,然后再返回;结果应该 比较等于原始指针。
醇>
和
- 可以将指向一种类型的函数的指针转换为指向另一种类型的函数的指针 打字再回来;结果应该等于原始指针。如果转换了 指针用于调用类型与引用类型不兼容的函数, 行为未定义。
醇>
请注意,没有提到混合对象和函数指针的可能性。它似乎可以在某个系统上运行,但它的行为是未定义的,并且不能保证有效。
但是,您可以创建包装器对象并传递该地址:
struct wrapper {
my_custom_callback_t func;
};
struct wrapper my_wrapper = { my_custom_callback };
someAPIFunction( /*...*/, standard_callback, &my_wrapper);
或只是将指针传递给函数指针(函数指针变量是对象类型):
my_custom_callback_t func = my_custom_callback;
someAPIFunction( /*...*/, standard_callback, &func);
答案 1 :(得分:2)
大多数平台实际上允许您将函数指针作为void *传递,但理论上不允许这样做。代码可能有不同的数据指针。您也无法将const限定地址传递给void *。
答案 2 :(得分:1)
正如已经指出的那样,在一般情况下不允许这样做,您可能会收到编译器警告。这是因为有些平台的函数指针比数据指针大。
然而,更常见的情况是指针大小确实相等。用于访问dlsym()
或GetProcAddress()
等共享对象的接口实际上依赖于此。
因此,如果您确定所有目标平台将使用与数据指针相同的函数指针大小,则可以通过首先转换为数据指针使其明确(因此编译器不会发出任何警告)。 uintptr_t
。所有指针类型都允许使用整数转换,只要整数足够大以容纳指针,就可以使用。保证uintptr_t
足够大以容纳数据指针,因此如果函数指针的大小相同,那就没问题了。