2012-01-16 155 views
10

我有在H文件中定義的static inline功能,並在一個C文件中的一個點,我指定一個函數指針,是這樣的:C:指針內聯函數

了foo.h :

static inline void frobnicate(void) { 
    // frobs something. 
} 

foo.c的

#include "foo.h" 

void execute(void (*func)(void)) { 
    func(); 
} 

void blahBlahBlah(void) { 
    execute(frobnicate); 
} 

bar.c

#include "foo.h" 
// ... 
frobnicate(); 

所以我認爲在這裏會發生的事情是,編譯器將內聯從bar.c中調用frobnicate,但在foo.c中,它實際上必須創建一個函數來實現frobnicate,以便它可以工作指向它的指針。

任何人都可以確認我的理解是否準確,否則糾正我?

+2

*您可以通過閱讀生成的代碼進行確認。我不認爲這個*具有特定的工作方式。如果編譯器「有人想要這個地址,那麼我們就不要內聯」。 – unwind 2012-01-16 20:10:03

+7

請記住,'inline'對於編譯器來說只是一個_suggestion_。 – 2012-01-16 20:10:23

回答

10

inline是C標準的誤稱之一。它的主要含義是能夠將函數的定義放在頭文件中,而不必在鏈接時處理「多重定義」問題。

C99和C11中的官方方式是要在頭文件中有inline定義,而不是static。由於您還需要發佈符號,因此您需要告訴編譯器應該在哪個編譯單元中進行編譯。這種實例化可以通過在該.c文件中具有聲明來完成,其中您省略了inline關鍵字。

很自然地,你可以在你實際需要符號的地方使用.c文件。

+0

如果內聯定義位於不帶'static'的頭文件中,那麼當我嘗試鏈接時,是否會出現同名多個定義(內聯函數)? – brianmearns 2012-01-16 20:29:44

+0

您將遇到鏈接問題。要麼使其成爲「靜態內聯」,並冒着多種定義的風險,或者放棄內聯。你也可以創建一個包裝器,它將在一個C文件中,並且不會內聯,並且指向它(不會影響性能,因爲真正的函數將被內聯到包裝器中)。 – ugoren 2012-01-16 21:38:07

+0

@bmearns,與C99兼容的編譯器,你將沒有聯繫問題。這正是'inline'關鍵字的意義。 http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ – 2012-01-17 10:48:01

7

是的,你是對的。當您將指針指向函數時,編譯器必須創建一個「獨立」版本,其中代碼可以作爲普通函數調用。

內聯函數的好處是不需要創建調用代碼,並且可以使用任何其他優化來集成調用者函數和內聯函數。但是當你需要定期調用函數時(就像你用地址來調用它),那些優化是不可能的。

+2

對許多編譯器來說,這可能是正確的,但我不能想象爲什麼需要編譯器來這樣做。即使在函數指針的情況下,OP的例子也可以很容易地內聯。 – 2012-01-16 20:31:26

+0

'inline'是一個建議。如果編譯器不能內聯,它不會,如果不能,它可能仍然決定不要(即使沒有'inline'關鍵字,它也可能內聯)。函數指針通常可以防止內聯,但在這種情況下,編譯器可能會發現它們不會(或者不會打擾)。 – ugoren 2012-01-16 21:35:11

+0

是的,在這種情況下,可以內聯該功能。我認爲這是該問題的簡化版本。但你是對的。 – Governa 2012-01-17 13:06:53