在POSIX系统上,argc可以为零吗?

Syl*_*oux 73 c posix program-entry-point language-lawyer

鉴于主程序的标准定义:

int main(int argc, char *argv[]) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

argcPOSIX系统在哪些情况下可以为零?

dbu*_*ush 89

对的,这是可能的.如果您按如下方式致电您的计划:

execl("./myprog", NULL, (char *)NULL);
Run Code Online (Sandbox Code Playgroud)

或者:

char *args[] = { NULL };
execv("./myprog", args);
Run Code Online (Sandbox Code Playgroud)

然后在"myprog"中,argc将为0.

该标准还特别允许argc在5.1.2.2.1节中提到的关于托管环境中的程序启动的0 :

1命名程序启动时调用的函数main.该实现声明此函数没有原型.它应定义为返回类型int且没有参数:

int main(void) { /* ... */ } 
Run Code Online (Sandbox Code Playgroud)

或者有两个参数(这里称为argcargv,虽然可以使用任何名称,因为它们是声明它们的函数的本地名称):

int main(int argc, char *argv[]) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

或同等学历; 或者以某种其他实现定义的方式.

2如果声明它们,main函数的参数应遵循以下约束:

  • argc应为非负值.
  • argv[argc] 应为空指针.

...

另请注意,这意味着如果argc为0则argv[0]保证为NULL.printf当用作%s指定符的参数时,如何将NULL指针视为标准中没有拼写出来.在这种情况下,许多实现将输出"(null)",但我不相信它是有保证的.

  • @SylvainLeroux你(和其他人稍后阅读这个答案)可能会觉得有趣的是,除了关于一般情况的文档之外,从几年前开始,*one*系统旨在符合POSIX标准**实际上无法使用`argc == 0`调用程序:OpenBSD. (6认同)

Pos*_*sum 22

要添加到其他答案,C(POSIX与否)中没有任何内容阻止main()作为程序中的函数被调用.

int main(int argc, int argv[]) {
    if (argc == 0) printf("Hey!\n");
    else main(0,NULL);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • ......嗯 我认为这是特别禁止的,但事实证明只有C++才能做到这一点,C就可以了. (10认同)

Tom*_*m's 18

是的,它可以是零,这意味着argv[0] == NULL.

这是一个惯例,argv[0]是程序的名称.你可以拥有argc == 0自己的二进制文件,就像使用execve系列一样,不要给出任何参数.您甚至可以提供一个远不是程序名称的字符串.这就是为什么argv[0]用来获取程序名称并不完全可靠.

通常,键入命令行的shell总是将程序名称添加为第一个参数,但同样,它是一种约定.如果argv[0]==" - help"并使用getopt解析选项,则不会检测到它,因为optind初始化为1,但您可以设置optind为0,使用getopt和"help"长选项将显示.

长话短说:完全可能拥有argc == 0(argv[0]本身并不特别).当发射器根本不给出参数时就会发生这种情况.

  • 好吧,' - help'是一个合法的文件名,所以,为什么argv [0]不能' - help'? (6认同)
  • “这是惯例”的措辞有点不准确。不遵循该“约定”的程序不符合 POSIX(阅读文档的“基本原理”部分)。因此,虽然很可能做一些不同的事情,但这样做是不合规的。这是否是人们应该期望发生的事情(因为它是可能的)是有争议的。我在“不支持损坏的软件”团队中。 (2认同)
  • @CharlesDuffy:这就是我们如何陷入标签汤(HTML怪癖模式),垃圾邮件(SMTP滥用)以及随机国家的常规互联网黑客攻击(糟糕的BGP推送).如果有人违反了标准,并且没有历史原因允许他们这样做,那么你应该失败.高声. (2认同)

Sta*_*eur 15

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

严格符合POSIX应用程序的要求还指出,作为第一个参数传递的值是与正在启动的进程关联的文件名字符串.虽然某些现有应用程序在某些情况下传递路径名而不是文件名字符串,但文件名字符串通常更有用,因为argv [0]的常见用法是在打印诊断中.在某些情况下,传递的文件名不是文件的实际文件名; 例如,登录实用程序的许多实现使用前缀(' - ')到实际文件名的约定,这表示命令解释器被调用它是"登录shell".

另请注意,测试和[实用程序需要argv [0]参数的特定字符串才能在所有实现中具有确定性行为.

资源


在POSIX系统上,argc可以为零吗?

是的,但它不会严格符合POSIX.

  • "POSIX系统"是否意味着"系统中的每个程序都是'严格符合POSIX应用程序'"?真正的问题 - 我不知道关于这个问题的标准的迂腐语义.我知道我可以采用一个被认证为POSIX系统的系统,并且在其上编写/运行一个不是"严格符合POSIX应用程序"的程序,我不确定它是否是预期的含义. POSIX标准是说当系统上安装了任何非严格一致的第三方应用程序时,系统会变得不符合要求吗? (2认同)