为了账号安全,请及时绑定邮箱和手机立即绑定

C函数指针转换为void指针

/ 猿问

C函数指针转换为void指针

C
慕运维1137616 2019-10-21 13:05:52

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


文件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));

}

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


查看完整描述

3 回答

?
冉冉说

C标准不允许将函数指针转换为void*。您只能转换为其他函数指针类型。在C11标准6.3.2.3§8中:


指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再次返回


重要的是,在使用指针调用该函数之前,必须先强制转换回原始类型(从技术上讲,是兼容类型。在6.2.7中定义为“ compatible” )。


请注意,由于使用的上下文不同,许多(但不是全部)C编译器也必须遵循POSIX标准,该标准要求可以将函数指针转换为void*反向。这对于某些系统功能(例如dlsym)是必需的。


查看完整回答
反对 回复 2019-10-21
?
波斯汪

不幸的是,该标准不允许在数据指针和函数指针之间进行强制转换(因为在某些晦涩难懂的平台上可能没有意义),即使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


查看完整回答
反对 回复 2019-10-21
?
DIEA

关于数据指针和代码指针,我有三个经验法则:


千万不能混用数据指针和代码指针

不要混用数据指针和代码指针

永远不要混合使用数据指针和代码指针!

在以下功能中:


void setCallback(const void *fnPointer)

{

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

}

您有一个指向函数指针的数据指针。(更不用说您通过首先获取指针本身的地址,然后将其转换为指向指针的指针,然后再取消对其引用)来执行此操作。


尝试将其重写为:


void setCallback(FN_GET_VAL fnPointer)

{

     gfnPtr = fnPointer;

}

另外,您可以(或应该)在设置指针时放弃演员表:


main()

{

   setCallback(myfunc);

   gfnPtr();

}

另外,您现在可以使用编译器执行的常规类型检查。


查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信