2011-11-05 161 views
25

我相信源文件中的靜態函數不能直接從文件外調用。但是,如果我以某種方式設法將此函數的指針轉換爲另一個文件,那麼我可以從該文件調用此函數。如果是的話,是否有任何情況下我們想採取這種路線,而不是簡單地使該功能非靜態?可以通過C中的函數指針調用靜態函數嗎?

+1

我想知道如果你將這與'inline'關鍵字和/或專有的編譯器指令混合使用,它總是內聯一個函數,那麼行爲是什麼。 – mpontillo

+0

@mpontillo我相信,即使函數被標記爲「inline」,但地址是在函數指針中取得的,編譯器會在二進制文件中生成主體,同時也將其內聯到同一模塊中的其他函數中。 –

回答

28

是的,你可以通過發出指向它們的靜態函數。這是在C語言中實現Factory pattern的常用方法,您可以在其中隱藏使用它們的模塊中的一大堆函數的實現,並且有一個FuncPtr_t GetFunction(enum whichFunctionIWant)將它們傳遞給消費者。這就是多少個dynamic linking實現的工作。

3

是的,文件中的非靜態函數可以將指向靜態函數的指針返回到任何你喜歡的位置。

9

但是,如果我設法得到一個指向這個函數的指針到 另一個文件,我可以從那個文件中調用這個函數。

是的,這是完全可能的。該函數對鏈接器不可見,但它在可執行文件中。你總是可以跳轉到它的地址。

雖然我不確定情況。也許你想讓其他人只在之後調用你的函數他們調用了一些其他函數(當然是非靜態的)。所以你有他們它獲得它,然後他們可以打電話給它。

3

是的,你可以。如果您必須調用一個函數,該函數將函數的指針視爲回調函數,則可以使用static,以便函數符號不會污染全局名稱空間,並且不會導致鏈接器衝突。最常用的例子可能是qsort:

struct Data { ... }; 

static int compareData(const void* a, const void* b) { /* cast to Data and compare */ } 

... 
qsort(array, count, sizeof(Data), &compareData); 
4

正如另一個提到的,你可以做到這一點。爲什麼你可能想要某種「驅動程序」的例子。您可以傳回包含開放,關閉,讀取和寫入功能的結構,而無需公開實際的功能。

0

是的,你可以,你總是可以自己嘗試,並找出:

file1.c中

#include <stdio.h> 

void call_hello(void (*fptr)(void)); 

static void hello(void) { 
    puts("hello"); 
} 

int main(void) 
{ 
    void (*fptr)(void) = hello; 

    call_hello(fptr); 

    return 0; 
} 

file2.c中

void call_hello(void (*fptr)(void)) 
{ 
    fptr(); 
} 
+8

這在C中通常不是一個好方法。「它有效」和「它是安全的,可以在任何地方工作,並且不依賴於未定義的行爲」通常是非常不同的事情。 –

2

它往往是用於定義一個小的靜態函數作爲另一個工作者函數。看一下標準qsort的例子:它需要一個比較函數,而且通常最好是將該比較函數設置爲靜態的(例如,因爲它在其他地方沒有用處,並且因爲qsort希望它具有一些無害的簽名)。