C的main()函数的有效签名是什么?
这个问题在这里已经有了答案:
在答案时(C11),当前的标准明确提到了这两个:
int main(void);
int main(int argc, char* argv[]);
尽管它提到了以下脚注中的“或等同”一词:
因此, int
可以被定义为int
的typedef
名称替代,或者argv
的类型可以被写为char ** argv
,依此类推。
另外,它还提供了更多(实现定义的)可能性。
相关部分(C11中的5.1.2.2.1节,但这一特定方面与C99没有变化)表明:
程序启动时调用的函数名为main。 该实现没有声明这个函数的原型。 它应该用返回类型int和不带参数来定义:
int main(void) { /* ... */ }
或者带有两个参数(这里称为argc和argv,尽管可以使用任何名称,因为它们是声明它们的函数的本地):
int main(int argc, char *argv[]) { /* ... */ }
或同等学历; 或者以某种其他实现定义的方式。
如果声明它们,则主函数的参数应遵守以下约束条件:
argc
的值应该是非负的。
argv[argc]
应该是一个空指针。
如果argc的值大于零,则包含argv[0]
至argv[argc-1]
的数组成员应包含指向字符串的指针,这些字符串在程序启动之前由主机环境给定实现定义的值。 其目的是向程序提供在程序启动之前从托管环境中的其他地方确定的信息。 如果主机环境不能提供大写和小写字母的字符串,则实现应确保字符串以小写字母接收。
如果argc
的值大于零,则由argv[0]
指向的字符串表示程序名称; 如果程序名称在主机环境中不可用,则argv[0][0]
应为空字符。 如果argc
的值大于1, argv[1]
至argv[argc-1]
指向的字符串表示程序参数。
参数argc
和argv
以及argv
数组所指向的字符串应该可以通过程序修改,并在程序启动和程序终止之间保留最后存储的值。
请注意,这是针对托管环境的,通常在C程序中看到的环境。 独立环境(如嵌入式系统)的限制要少得多,如同一标准的5.1.2.1所述:
在一个独立的环境中(C程序的执行可能没有任何操作系统的好处),程序启动时调用的函数的名称和类型是实现定义的。 任何独立程序提供的图书馆设施,除第4条要求的最小集合外,都是实现定义的。
POSIX支持execve()
,后者又支持
int main(int argc, char *argv[], char *envp[])
添加的参数是环境,即NAME = VALUE形式的字符串数组。
标准C
对于托管环境(这是正常的),C99标准说:
5.1.2.2.1程序启动
程序启动时调用的函数名为main
。 该实现没有声明这个函数的原型。 它应该用返回类型int
和不带参数来定义:
int main(void) { /* ... */ }
或者带有两个参数(这里称为argc
和argv
,尽管可以使用任何名称,因为它们是声明它们的函数的本地):
int main(int argc, char *argv[]) { /* ... */ }
或等同物; 9)或以某种其他实施方式定义的方式。
9)因此, int
可以被定义为int
的typedef名称替代,或者argv
的类型可以被写为char **argv
,依此类推。
标准C ++
C ++ 98标准说:
3.6.1主要功能[basic.start.main]
1程序应包含一个称为main的全局函数,它是程序的指定开始。 [...]
2实现不应该预定义主函数。 该功能不得超载。 它应该有一个类型为int的返回类型,否则其类型是实现定义的。 所有的实现都应该允许main的以下两个定义:
int main() { /* ... */ }
和
int main(int argc, char* argv[]) { /* ... */ }
C ++标准明确地说:“它[主函数]应该有一个类型为int的返回类型,否则它的类型是实现定义的”,并且需要与C标准相同的两个签名。 因此,C ++标准直接不允许使用'void main()',尽管没有办法阻止非标准的实现允许其他选择。
共同扩展
传统上,Unix系统支持第三种变体:
int main(int argc, char **argv, char **envp) { ... }
第三个参数是一个以空字符结尾的字符串指针列表,每个字符串都是一个具有名称,等号和值(可能为空)的环境变量。 如果你不使用这个,你仍然可以通过' extern char **environ;
'来获得extern char **environ;
”。 很长一段时间,它没有声明它的头文件,但POSIX 2008标准现在要求它在<unistd.h>
声明。
这被C标准认可为一个通用扩展,记录在附录J中:
J.5.1环境参数
¶1在托管环境中,主函数接收第三个参数char *envp[]
,该参数指向以char
为空的终止指针数组,每个指向一个字符串,该字符串提供有关此执行的环境的信息(5.1.2.2.1)。
微软C
Microsoft VS 2010编译器很有趣。 该网站说:
main的声明语法是
int main();
或者可选地,
int main(int argc, char *argv[], char *envp[]);
或者, main
和wmain
函数可以声明为返回void
(无返回值)。 如果将main
或wmain
声明为返回void,则无法使用return语句将退出代码返回给父进程或操作系统。 要将main
或wmain
声明为void
时返回退出代码,您必须使用exit
函数。
当使用void main()
的程序确实退出时,我不清楚发生了什么(退出代码返回给父代或o / s) - 而且MS网站也是无声的。
有趣的是,MS并没有规定C和C ++标准要求的main()
的双参数版本。 它只规定了一个三参数形式,其中第三个参数是char **envp
,指向一个环境变量列表的指针。
微软的网页还列出了一些其他的选择 - wmain()
,它需要宽字符字符串等等。
此页面的Microsoft VS 2005版本没有列出void main()
作为替代。 微软VS 2008以后的版本可以。