C函数指针转换为void指针

我正在尝试运行以下程序,但出现一些奇怪的错误:


文件1.c:


typedef unsigned long (*FN_GET_VAL)(void);


FN_GET_VAL gfnPtr;


void setCallback(const void *fnPointer)

{

    gfnPtr = *((FN_GET_VAL*) (&fnPointer));

}

文件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 */

}

使用gcc编译时,gfnPtr()在64位suse linux上崩溃。但是它成功调用了gfnPtr()VC6和SunOS。


但是,如果我按如下所示更改功能,则它可以成功运行。


void setCallback(const void *fnPointer)

{

    int i; // put any statement here

    gfnPtr = *((FN_GET_VAL*) (&fnPointer));

}

请帮助解决问题的原因。谢谢。


千巷猫影
浏览 969回答 3
3回答

冉冉说

C标准不允许将函数指针转换为void*。您只能转换为其他函数指针类型。在C11标准6.3.2.3§8中:指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再次返回重要的是,在使用指针调用该函数之前,必须先强制转换回原始类型(从技术上讲,是兼容类型。在6.2.7中定义为“ compatible” )。请注意,由于使用的上下文不同,许多(但不是全部)C编译器也必须遵循POSIX标准,该标准要求可以将函数指针转换为void*反向。这对于某些系统功能(例如dlsym)是必需的。

波斯汪

不幸的是,该标准不允许在数据指针和函数指针之间进行强制转换(因为在某些晦涩难懂的平台上可能没有意义),即使POSIX和其他平台也需要强制转换。一种解决方法不是强制转换指针,而是强制将指针强制转换为指针(编译器可以这样做,并且它将在所有普通平台上完成工作)。typedef void (*FPtr)(void); // Hide the uglinessFPtr f = someFunc;          // Function pointer to convertvoid* ptr = *(void**)(&f);  // Data pointerFPtr f2 = *(FPtr*)(&ptr);   // Function pointer restored

DIEA

关于数据指针和代码指针,我有三个经验法则:千万不能混用数据指针和代码指针不要混用数据指针和代码指针永远不要混合使用数据指针和代码指针!在以下功能中:void setCallback(const void *fnPointer){    gfnPtr = *((FN_GET_VAL*) (&fnPointer));}您有一个指向函数指针的数据指针。(更不用说您通过首先获取指针本身的地址,然后将其转换为指向指针的指针,然后再取消对其引用)来执行此操作。尝试将其重写为:void setCallback(FN_GET_VAL fnPointer){     gfnPtr = fnPointer;}另外,您可以(或应该)在设置指针时放弃演员表:main(){   setCallback(myfunc);   gfnPtr();}另外,您现在可以使用编译器执行的常规类型检查。
打开App,查看更多内容
随时随地看视频慕课网APP