Man*_*noj 20 c pointers function-pointers
我试图运行以下程序,但得到一些奇怪的错误:
档案1.c:
typedef unsigned long (*FN_GET_VAL)(void);
FN_GET_VAL gfnPtr;
void setCallback(const void *fnPointer)
{
gfnPtr = *((FN_GET_VAL*) (&fnPointer));
}
Run Code Online (Sandbox Code Playgroud)
档案2.c:
extern FN_GET_VAL gfnPtr;
unsigned long myfunc(void)
{
return 0;
}
main()
{
setCallback((void*)myfunc);
gfnPtr(); /* Crashing as value was not properly
assigned in setCallback function */
}
Run Code Online (Sandbox Code Playgroud)
这里使用gcc编译时,gfnPtr()在64位suse linux上崩溃.但它成功调用了gfnPtr()VC6和SunOS.
但如果我改变下面给出的功能,它就能成功运行.
void setCallback(const void *fnPointer)
{
int i; // put any statement here
gfnPtr = *((FN_GET_VAL*) (&fnPointer));
}
Run Code Online (Sandbox Code Playgroud)
请帮助解决问题的原因.谢谢.
Pas*_*uoq 37
该标准不允许将函数指针强制转换为void*
.您可能只会转换为另一个函数指针类型.6.3.2.3§8:
指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针并且再次返回
重要的是,在使用指针调用函数之前必须强制转换回原始类型(技术上,为兼容类型.在6.2.7中定义"compatible").
Tro*_*nic 14
遗憾的是,标准不允许在数据指针和函数指针之间进行转换(因为这可能在一些非常模糊的平台上没有意义),即使POSIX和其他人需要这样的转换.一种解决方法是不转换指针,而是转换指针指针(编译器可以这样做,它将在所有普通平台上完成工作).
typedef void (*FPtr)(void); // Hide the ugliness
FPtr f = someFunc; // Function pointer to convert
void* ptr = *(void**)(&f); // Data pointer
FPtr f2 = *(FPtr*)(&ptr); // Function pointer restored
Run Code Online (Sandbox Code Playgroud)
当涉及到数据指针和代码指针时,我有三条经验法则:
在以下功能中:
void setCallback(const void *fnPointer)
{
gfnPtr = *((FN_GET_VAL*) (&fnPointer));
}
Run Code Online (Sandbox Code Playgroud)
你有一个数据指针,你需要一个函数指针.(更不用说你通过首先获取指针本身的地址,将它转换为指向指针的指针,然后取消引用它)来实现这一点.
尝试将其重写为:
void setCallback(FN_GET_VAL fnPointer)
{
gfnPtr = fnPointer;
}
Run Code Online (Sandbox Code Playgroud)
此外,您可以(或应该)在设置指针时删除强制转换:
main()
{
setCallback(myfunc);
gfnPtr();
}
Run Code Online (Sandbox Code Playgroud)
作为额外的奖励,您现在可以使用编译器执行的常规类型检查.