2010-05-08 17 views
22

我對從命令行向main()傳遞參數的理解是,argc的最小值爲1,argv [0]將始終具有程序名稱及其路徑。argv [0]何時可以爲null?

如果在命令行中提供參數,則argc的值將大於1,argv [argc-1]將具有這些參數的argv 1

現在在this link一個段落說,

的argv [0]將包含該程序的名稱或空字符串如果這是不可用的字符串。

現在,如何以及何時可以argv [0]有空字符串?我的意思是程序名稱及其路徑將始終可用,因此何時可以爲空?

作家說,「如果不可用」,但何時以及如何有可能程序名稱將不可用?

+1

@ShaunHamman目前的共識是關閉「質量」:http://meta.stackexchange.com/questions/147643/should-i-vote-to-close-a-duplicate-question-ven-though-its-much因爲「質量」是不可衡量的,所以我只是通過點贊。 ;-)可能歸結爲哪個問題在標題上碰到了最好的newb Google關鍵詞。 – 2017-02-17 20:20:42

回答

22

隨着exec調用類的,您所指定的程序和程序可執行分開,所以你可以將其設置爲null,則。

但是這個引用實際上是來自ISO標準(可能是釋義),並且該標準覆蓋了從最小的微控制器到最新的z10企業級大型機的大量執行環境。

許多這些嵌入式系統將處於可執行名稱毫無意義的情況。

從最新的C1X草案:

argc值應爲正數。

argv[argc]應爲空指針。

如果argc值大於零,陣列成員argv[0]通過argv[argc-1]包容應包含指向字符串,其通過現有主機環境給定實現所定義的值來編程啓動。

這意味着,如果argc爲零(也可以是),則argv [0]爲NULL。

但是,即使argc 0,你可能無法獲得程序的名稱,因爲標準還規定:

如果argc的值大於零,則指向的字符串argv[0]代表程序名稱;如果程序名稱在主機環境中不可用,則argv[0][0]應爲空字符。如果argc的值大於1,則由argv[1]argv[argc-1]指向的字符串表示程序參數。

因此,在標準下沒有要求提供程序名稱的要求。我已經看過程序對此值使用多種選項:

  • 根本沒有值(對於假定的安全性)。
  • 一個公然的謊言(例如sleep惡意代碼段)。
  • 實際的程序名(例如sleep)。
  • 稍微修改一個(例如登錄shell的-ksh)。
  • 描述性名稱(例如,progname - a program for something)。
5

根據this mailing listargv[0]可以爲空,如果argc == 0。但是他們沒有解釋argc可能永遠爲零。我會嫌疑人argc在可執行文件沒有「正常」啓動(即通過命令行,popen等)的情況下爲零,事實上,如提到的@paxdiablo,您可以使用exec family of functions手動設置argv ,所以根據這些參數,argc可能爲零。

但是,在他們的理由部分:

要求的argc傳遞給main()值是「一個或更多的」早期建議。這是由ISO C標準草案中的相同要求所驅動的。實際上,當沒有參數提供給exec函數的調用者時,歷史實現已經傳遞了零值。該要求已從ISO C標準中刪除,並隨後從IEEE Std 1003.1-2001的這一卷中刪除。措辭,特別是使用單詞should,需要一個嚴格符合的POSIX應用程序向exec函數傳遞至少一個參數,從而保證當被這樣的應用程序調用時,該函數應該是一個或多個參數。事實上,這是一個很好的做法,因爲許多現有應用程序參考argv[0]而沒有首先檢查argc的值。

所以你有它:嚴格符合POSIX應用程序必須有argc大於零,但這是不能保證。

有關argcargv的標準Program Startup部分的更多信息。

1

可以想象平臺的程序沒有名字 - 也許代碼只是在啓動時加載。在那些上,argv [0]我猜可能是NULL。 C標準肯定允許argc值爲零,並且說argv [argc]應爲NULL。

0

可運行POSIX例如

a.c

#define _XOPEN_SOURCE 700 
#include <unistd.h> 

int main(void) { 
    char *argv[] = {NULL}; 
    char *envp[] = {NULL}; 
    execve("b.out", argv, envp); 
} 

b.c

#include <stdio.h> 

int main(int argc, char **argv) { 
    if (argc == 0 && argv[0] == NULL) 
     puts("yup"); 
} 

然後:

gcc a.c -o a.out 
gcc b.c -o b.out 
./a.out 

給出:

yup 

在Ubuntu 16.10測試。