2010-04-21 84 views
19

今天,看着爲open()手冊頁,我發現這個功能是「超載」:函數重載用C

int open(const char *pathname, int flags); 
    int open(const char *pathname, int flags, mode_t mode); 

我不認爲這是可能的C.有什麼「絕招」爲了實現這個?

以後編輯:
所以它不是真正的超載,採用可變參數的時候,因爲 - 你只能提供相同類型的多個參數。那麼,mode_t幕後一個int?

+0

mode_t確實是一個整數,但可以提供不同類型的參數,假設你知道如何解釋它們。 printf函數家族使用格式字符串來了解如何解釋其額外參數,即使它們的輸入方式不同。下面的答案有一些例子可以說明這一點。 – 2010-04-21 19:41:48

+0

@Eli謝謝,我一定對Java感到困惑。 – 2010-04-21 19:47:07

+0

像這樣的函數被稱爲可變參數函數。 – Chris 2012-01-22 19:22:55

回答

30

它使用variable arguments名單。這些聲明只出現在手冊頁中,因爲這2個是你應該調用open()的唯一方法。實際的C函數將被聲明爲例如

int open(const char *pathname,int flags,...); 

使用可變參數時,參數不需要是相同的類型。 printf就是這個例子。

在open()的情況下,如果'flags包含O_CREAT標誌,則第一個變量參數必須爲mode_t,因爲open()的實現需要它爲mode_t(後臺可能是unsigned int或unsigned長 - 但與可變參數無關)

3

非常簡短的回答 - 可變參數

+0

並敲定downvotes正確的答案 - 簡潔是一種美德。 – KevinDTimm 2010-04-22 18:54:12

2

您可以僞造它使用可變參數與...

int function(int x, ...); 
6

「當O_CREAT在標誌中時,必須指定」模式,否則將被忽略。「

extern int open (__const char *__file, int __oflag, ...)

它採用varargs如果__oflag包含O_CREAT只加載模式可變參數。

10

C確實可以用variable number of argument來編寫函數,例如printf。這就是說,在C中沒有可靠的,跨平臺的方式來編寫一個只需要2或3個參數的函數;在一般情況下,你必須做類似

some_function(5, 6, 7, NULL); 
some_function(5, 6, 8, 2, 5, NULL); 

換句話說,你必須有一個終止的「sentinal」參數。另外,還可以包括以某種方式在前面的參數參數的個數,如

another_func(2, "hello", "world"); 
another_func(3, "goodbye", "cruel", "world"); 

printf系列函數採取這種方式;第一個格式參數包含所需的額外參數的數量;例如與printf("%f %f", 5.6, 7.11)你知道必須有2個浮點參數。然而,這在用戶定義的庫函數中會有些不安全,因爲如果你說my_printf("%s %f %f %f %s", 5.6)那麼你可能會發生段錯誤或更糟。幸運的是,大多數C編譯器會在編譯時檢查您的電話號碼爲printf以避免此類問題。

open的情況下,該函數被聲明爲具有可變參數,並且僅在設置了O_CREAT的情況下才檢查第三個參數。所以這就是它如何「安全」地確定是否存在第三個參數。我把「安全地」放在引號中,因爲從技術上講,在運行時沒有辦法知道在運行時實際傳遞了多少個參數。例如,下面的調用將編譯沒有任何錯誤或警告:

open("foo.txt", 5, "not an integer", 7); // extra and invalid parameters 
open("bar.txt", O_CREAT);     // third parameter is missing 
+1

如果'some_function()'需要'int's,則不應該用'NULL'結束它,因爲NULL在數值上下文中僅爲0。 'NULL'結束符與指針參數一起使用效果最佳。 – 2010-04-21 19:47:56

+0

@Chris:好的,我通常使用NULL作爲終止符,而不管數據類型如何,但是你說得對,可能會讓人困惑,特別是對於不知道0和NULL是否相同的人,因爲他們可能會想他們可以寫'some_func(3,2,1,0,-1,NULL)',事實上這會導致0作爲終止參數。 – 2010-04-21 20:05:22

+1

最近版本的gcc和glibc頭文件會一起爲您的最後兩個示例產生警告。 – caf 2010-04-21 23:22:08