我正在使用微控制器。在调试时,必须调用一个在ROM中硬编码的函数。技术参考说明了如何执行此操作:
# define Device_cal (void(*)(void))0x3D7C80
并且调用过程如下所示:
(*Device_cal)()
我无法理解这里发生了什么,所以我的问题是: 它是如何工作的?
答案 0 :(得分:7)
void (*) (void)
是一种类型。它是一个指向函数的指针,该函数不带参数并返回void
。
(void(*)(void)) 0x3D7C80
将0x3D7C80
整数强制转换为此函数指针。
(*Device_cal)()
调用该函数。
(Device_cal)()
会完全一样。
*Device_cal
和Device_cal
周围的括号是必需的,否则对整数的强制转换不会有更高的优先级。
答案 1 :(得分:3)
#define
会导致(*Device_cal)()
在编译前立即展开:
(*(void(*)(void))0x3D7C80)()
void(*)(void)
是函数指针的声明,它采用void
并返回void
类型。 (*())
表示表达式(0x3D7C80
)中下一个标记的强制转换。因此,这要求将位置0x3D7C80
处的数据视为一个函数。最后的()
调用没有参数的函数。
答案 2 :(得分:2)
好吧,你“定义”一个指向函数的指针,然后调用它。
void(*)(void)
表示指向函数的指针,它不带参数,并返回void
。
如果您将0x3D7C80
强制转换为该类型并调用它,则基本上会调用其地址为0x3D7C80
的函数。
答案 3 :(得分:2)
这不是一个答案(已经令人满意地完成),但有些建议:
我建议使用以下方法:
typedef void (*tVOID_ROMFUNCTION_VOID)( void ) ;
tVOID_ROMFUNCTION_VOID Device_cal = (tVOID_ROMFUNCTION_VOID)0x3D7C80 ;
Device_cal() ;
这样,您可以在初始化时创建任意数量的全局函数指针,而调用看起来像普通的静态链接函数。并且您可以避免同时混淆预处理器宏voodoo。
通过创建具有不同签名的不同函数指针类型,编译器也可以为您执行一些参数类型检查。
答案 4 :(得分:0)
粘贴符号,在其中创建一个指向固定内存位置的函数的临时(未命名)指针,然后通过解除引用来调用它。