2013-10-06 76 views
6

最近我在寫一個文件打開程序時遇到了一個問題。如何在C中使用可選參數來創建函數?

讓我清楚地解釋我的問題。在這裏,我以open電話爲例。

要創建文件:

open("file_name", O_CREAT, 0766); //passing 3 parametrs 

打開一個文件:

open("file_name", O_RDWR); //only 2 arguments. 

然後我清楚地觀察到了這一點,它也適用於main()了。

main(void) //worked 
main(int argc, char **argv); //worked 
main(int argc) //worked and it's doesn't give an error like "too few arguments". 
main() //worked 

那麼我們如何創建這些可選參數呢?編譯器如何驗證這些原型?如果可能的話,請寫一個示例程序。

+0

相關:http:// stackoverflow。com/q/18421735/1870232 – P0W

回答

7

open函數被聲明爲可變參數函數。它看起來像這樣:

#include <stdarg.h> 

int open(char const * filename, int flags, ...) 
{ 
    va_list ap; 
    va_start(ap, flags); 

    if (flags & O_CREAT) 
    { 
     int mode = va_arg(ap, int); 
     // ... 
    } 

    // ... 

    va_end(ap); 
} 

除非您已經指出他們確實存在,否則不會消耗更多的參數。

對於printf使用相同的結構。

本手冊並不總是明確這一點,因爲唯一可能的兩個簽名是(char const *, int)(char const *, int, int),所以說明你實際上接受可變參數是沒有意義的。 (你可以通過編譯類似於open("", 1, 2, 3, 4, 5, 6)的方法來測試。)

+0

但他們如何驗證這些。它沒有給出像「太少爭論」這樣的論點。 – SGG

+0

@SGG:與'printf'可以驗證您是否傳遞了正確的參數數量和類型相同的方式。 –

+0

@KerrekSB:對不起,我錯過了清晰度。看看有一個函數需要一個參數或沒有任何東西(void)。我的意思是,函數應該是有效的,如果我調用函數()或函數(10)。你能寫出這個函數的定義嗎? – SGG

1

在所有情況下,可變參數函數必須能夠以固定參數的方式確定有多少可變參數。例如,printf()函數系列使用格式字符串來確定參數的數量和類型。 execl()函數使用標記(空指針)來標記參數列表的末尾。可以使用count來代替sentinel(但是如果你打算這麼做的話,那麼在non-varargs函數中的count和array可能會起作用,如果不是更好,計數和參數列表)。 open()函數使用其中一個標誌位來確定模式是否應該存在 - 請參閱Kerrek SBanswer

main()函數是一個特例。禁止實現(編譯器)爲其聲明原型,並且必須接受至少兩種形式:

int main(int argc, char **argv); 
int main(void); 

或其等同物。它也可以接受其他形式;請參閱What's the use of the third environment variable in the C main()?瞭解一種常見形式。在C中,但不是C++,標準編譯器可以記錄其他返回類型 - 而且Microsoft已將void記錄爲從VS 2008起的有效返回類型。

因爲沒有實現提供的原型爲main(),編譯器不能正式拒絕任何聲明/的main()定義,儘管它可能通過對無法識別的形式評論(GCC不上main()函數做評論例如,不返回int類型)。

+1

實際上,編譯器*可以*拒絕它不接受的'main'形式。替代形式是實現定義的,這意味着編譯器必須附帶列出它們的文檔。一個定義既不是兩種標準形式之一,也不是當前編譯器的實現定義形式的定義的程序具有未定義的行爲(由於該標準沒有定義行爲,因此省略)(5.1.2.2.1)。拒絕翻譯單位是對未定義行爲的可接受的反應(3.4.3)。 –

相關問題