什么时候argv 有空?

关于从命令行向main()传递参数,我所理解的是argc的最小值为1,而argv [0]将始终具有程序名称及其路径。

如果在命令行提供了参数,那么argc的值将大于1 ,而argv [argc-1]的argv将具有这些参数。

现在这个链接的段落说明了这一点

argv [0]将是包含程序名称的字符串,如果不可用,则为空字符串

现在,argv [0]如何以及何时可以使用空字符串? 我的意思是程序名称及其路径将始终可用,所以什么时候它可以为空?

作家说“如果不可用”但是何时以及如何可能无法获得程序名称?

使用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 )。

根据此邮件列表 ,如果argc == 0 ,则argv[0]可以为null。 但他们没有解释argc 何时可能为零。 我怀疑 argc在没有“正常”启动可执行文件的情况下会为零(即通过命令行, popen等) – 事实上,正如@paxdiablo所提到的,你可以手动设置argvexec系列函数 ,因此argc可能为零,具体取决于这些参数。

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

早期的提案要求传递给main()argc值为“一个或多个”。 这是由ISO C标准草案中的相同要求驱动的。 实际上,当没有向exec函数的调用者提供参数时,历史实现已经传递了零值。 此要求已从ISO C标准中删除,随后也从IEEE Std 1003.1-2001的该卷中删除。 措辞,特别是单词的使用应该要求严格一致的POSIX应用程序将至少一个参数传递给exec函数,从而保证在这样的应用程序调用时argc为1或更大。 实际上,这是一种很好的做法,因为许多现有的应用程序在没有首先检查argc的值的情况下引用了argv[0]

所以你有它:严格符合POSIX应用程序必须具有大于零的argc ,但这绝不是保证。

有关关于argcargv标准的更多信息,请参阅Program Startup部分。

可以想象程序没有名称的平台 – 也许代码只是在启动时加载。 在那些,argv [0]我可以猜测是NULL。 C标准当然允许argc值为零,并且表示argv [argc]应为NULL。

Runnable POSIX示例

ac

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

bc

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

然后:

 gcc ac -o a.out gcc bc -o b.out ./a.out 

得到:

 yup 

在Ubuntu 16.10中测试过。

使用空参数列表测试现有程序

这是一个以路径为参数的包装器,并将其作为没有args的命令运行:

 #include  #include  int main(int argc, char**argv) { char *empty[] = {NULL}; execve(argv[1], empty, empty); perror("empty-args: execve failed"); // Bad Address (EFAULT) if our argv[1] == NULL return 1; } 

用法:

 ./empty-args ./arg-count