如何解决将 foo(int *) 作为参数传递给 X 中的 foo(void*)
void somefunc(void func(void *)) { ... }
void foo(int *num) {...}
我试图将 foo 作为参数传递给 somefunc 但收到警告。 这样做的正确方法是什么?
解决方法
具有一个带有一个或多个 void *
参数的函数的参数是实现某些类型泛型算法的常用方法。 (此答案假设此代码中的情况如此。其他可能性存在但不太可能。) func
到 somefunc
的参数提供了 somefunc
用于对数据进行操作的回调函数不知道它的类型。
请注意,虽然参数声明为函数 void func(void *)
,但它会自动调整为指向函数 void (*func)(void *)
的指针。除去名称,我们得到抽象类型 void (*)(void *)
。
您不能为 void (*)(int *)
参数传递 void (*)(void *)
参数,因为它们是不兼容的类型。并且您不应该尝试通过强制转换将 foo
参数强制转换为参数类型,因为使用转换后的指针调用 void (int *)
函数的行为不是由 C 标准定义的。正确的解决方案是将指针传递给预期类型的函数。您可以为此创建一个新函数:
void FooWrapper(void *p) { foo(p); }
然后您可以将 FooWrapper
传递给 somefunc
。当 somefunc
调用 FooWrapper
时,它会传递一个 void *
。当 FooWrapper
调用 foo
时,该 void *
将自动转换为 int *
。 (大概,foo
是预先声明的,带有原型。)只要 void *
传递的 FooWrapper
起源于指向某个 int
的指针,这种从 {{ 1}} 回到 void *
是由 C 标准定义的,所以这是正确的代码。
或者,您可以修改 int *
以获取 foo
参数并将其在内部转换为 void *
,而不是创建包装器:
int *
然后您可以将 void foo(void *VoidNum)
{
int *num = VoidNum;
…
}
直接传递给 foo
。
我试图将 foo 作为参数传递给 somefunc 但收到警告。
发生错误是因为 somefunc
被声明为期望类型为 void (*)(void *)
的参数,但传递的参数 foo
的类型为 void (*)(int *)
。这两种类型不同且不兼容。
这样做的正确方法是什么?
函数指针可以在不同类型之间转换,所以下面的编译不会出错。
void bar() { somefunc((void (*)(int *))foo); }
使用辅助 typedef
使相同的代码更具可读性。
typedef void (*VOID_FUNC)(void *);
void bar() { somefunc((VOID_FUNC)foo); }
重要的警告是,唯一合法/安全地使用 func
中的 somefunc
参数是将其转换回真实的使用原始函数之前的类型。来自语言标准中的相关段落 6.3.2.3/8:“指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再返回;结果应与原始值相等指针。 如果使用转换后的指针调用类型与引用类型不兼容的函数,则行为未定义。"
以下是正确用法的缩写示例。
extern int n;
void foo(int *num);
typedef void (*VOID_FUNC)(void *);
typedef void (*INT_FUNC)(int *);
void somefunc(VOID_FUNC func) { ((INT_FUNC)func)(&n); }
void bar() { somefunc((VOID_FUNC)foo); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。