2016-02-10 35 views
0

我讀code of the bitcoin trezor MCU,發現這個:的C函數++(無效(**)())奇怪的鑄造

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

通過打破一些東西,我試着來分析一下這一行的意思是:

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

我可以看到,這是一個沒有參數的函數調用,由於()末,並且該功能是什麼

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

指向。

我知道FLASH_APP_START + 4將解決到的東西,所以我只需要弄清楚的是:

*(void (**)()) 

它解析爲任何void (**)()點。但是什麼是void (**)()?也許,它看起來像一個函數的轉換。但我不確定。你能給我一個這個叫什麼的例子嗎?你爲什麼需要這個?

回答

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是您的朋友。

+0

返回void的函數有什麼意義? – Gatonito

+0

你爲什麼使用typedef?它使我困惑,有沒有一種方法來使用它沒有typedef?你怎麼能重寫'空白'?是否允許? – Gatonito

+0

@Gatonito函數是一個可以用來打包代碼的抽象。它不需要返回任何東西,這只是一種切斷事物的方式,使人類更容易消化。具有巨大功能的代碼很難理解。編譯器和機器都不關心函數是否返回任何東西。 –

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。我們得到函數入口地址。將其轉換爲函數指針,然後調用它。

+0

參數列表'()'表示C中未指定的參數'(void)'表示沒有參數。 –

+0

@ M.M好的。感謝您的評論。 – Holsety