c ++中函数的奇怪转换(void(**)())

时间:2016-02-10 03:06:03

标签: c pointers casting trezor

我正在阅读code of the bitcoin trezor MCU并发现了这个:

(*(void (**)())(FLASH_APP_START + 4))();

通过分解一些东西,我试图分析这条线的含义:

(   *(void (**)())(FLASH_APP_START + 4)    )      ();

我可以看到这是一个没有参数的函数调用,因为最后是(),而且函数是什么

*(void (**)())(FLASH_APP_START + 4)

指向。

我知道FLASH_APP_START + 4会解决某些事情,所以我只需要弄清楚这是什么:

*(void (**)())

它正在解决任何void (**)()点。但是什么是void (**)()?它看起来像是一个函数的转换,也许。但我不确定。你能举个例子说明这个叫什么吗?你为什么需要那个?

2 个答案:

答案 0 :(得分:2)

(void (**)())的含义是:强制转换为指向函数返回void的指针。因此,当你取消引用它(*(void(**)()))时,它是函数返回void的类型指针,你可以调用它。 (FLASH_APP_START+4)是指向函数指针表的指针。如果FLASH_APP_START的类型为char*,则将调用列表中的第二个函数,假设32位指针。如果FLASH_APP_START的类型为void*,则会调用表中的第5个函数。

E.g。此代码将在具有32位指针的计算机上调用fun2

#include <stdio.h>

void fun1() { printf("fun1\n"); }
void fun2() { printf("fun2\n"); }

int main(void) {
  static void (*table[])() = { fun1, fun2 };

  int const FLASH_APP_START = (int)&table;
  (*(void (**)())(FLASH_APP_START + 4))();
}

如果您需要帮助解码C类型,cdecl.org是您的朋友。

答案 1 :(得分:0)

首先,void (**)()是指向函数指针的指针,没有参数和void返回类型。

其次,(void (**)())(FLASH_APP_START + 4)表示在第一步中将地址值FLASH_APP_START + 4强制转换为指针。 FLASH_APP_START应该是固定值。它可能是NAND闪存起始地址,总是在嵌入式系统中用作向量表。

第三,*(void (**)())(FLASH_APP_START + 4)取消引用第二步中获得的指针。我们现在有一个函数指针。

最后,(*(void (**)())(FLASH_APP_START + 4))()调用我们在第三步中获得的函数。

摘要:地址FLASH_APP_START + 4存储了一个函数入口地址。我们得到功能入口地址。将它转换为函数指针,然后调用它。