C的main()函数的有效签名是什么?

C中main函数的有效签名是什么? 我知道:

int main(int argc, char *argv[]) 

还有其他有效的吗?

这个答案(C11)当前的标准明确提到了这两个:

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

尽pipe它提到了“或同等”一词,并附有以下脚注:

因此, int可以被定义为inttypedef名称replace,或者argv的types可以被写为char ** argv ,依此类推。

另外,它还提供了更多(实现定义的)可能性。

相关部分(C11中的5.1.2.2.1节,但这个特定方面与C99没有任何变化)表示:

程序启动时调用的函数名为main。 这个实现声明了这个函数没有原型。 它应该用int的返回types来定义,并且不带参数:

 int main(void) { /* ... */ } 

或者带有两个参数(这里称为argc和argv,尽pipe可以使用任何名称,因为它们是声明它们的函数的本地):

 int main(int argc, char *argv[]) { /* ... */ } 

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

如果声明了,主函数的参数应该遵守以下约束条件:

  • argc的值应该是非负的。

  • argv[argc]应该是一个空指针。

  • 如果argc的值大于零,则argv[0]argv[argc-1]包含的数组成员应该包含指向string的指针,这些string在程序启动之前由主机环境给出实现定义的值。 其目的是向程序提供在程序启动之前从托pipe环境中的其他地方确定的信息。 如果主机环境不能提供大小写字母的string,则实现应确保string以小写forms接收。

  • 如果argc的值大于零,则argv[0]指向的string表示程序名称; 如果程序名称在主机环境中不可用,则argv[0][0]应为空字符。 如果argc的值大于1,则argv[1]argv[argc-1]指向的string表示程序参数。

  • 参数argcargv以及argv数组所指向的string应该可以被程序修改,并且在程序启动和程序终止之间保留它们的最后存储的值。

请注意,这是针对托pipe环境的,通常在C程序中看到的环境。 独立环境(如embedded式系统)的限制要less得多,如同一标准的5.1.2.1所述:

在一个独立的环境中(C程序的执行可能没有任何操作系统的好处),程序启动时调用的函数的名称和types是实现定义的。 任何独立程序提供的图书馆设施,除第4条所要求的最低限度设置外,都是实施定义的。

POSIX支持execve() ,这反过来支持

 int main(int argc, char *argv[], char *envp[]) 

添加的参数是环境,即NAME = VALUEforms的string数组。

标准C

对于托pipe环境(这是正常的),C99标准说:

5.1.2.2.1程序启动

程序启动时调用的函数名为main 。 这个实现声明了这个函数没有原型。 它应该用int的返回types来定义,并且不带参数:

 int main(void) { /* ... */ } 

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

 int main(int argc, char *argv[]) { /* ... */ } 

或同等学历; 9)或者其他一些实现定义的方式。

9)因此, int可以被定义为int的typedef名称replace,或者argv的types可以被写为char **argv ,依此类推。

标准C ++

C ++ 98标准说:

3.6.1主要function[basic.start.main]

1程序应该包含一个名为main的全局函数,它是程序的指定开始。 […]

2实现不应该预定义主函数。 该function不得超载。 它应该有一个types为int的返回types,否则其types是实现定义的。 所有的实现都应该允许main的以下两个定义:

 int main() { /* ... */ } 

 int main(int argc, char* argv[]) { /* ... */ } 

C ++标准明确地说“它的主函数应该有一个types为int的返回types,否则其types是实现定义的”,并且需要与C标准相同的两个签名。 所以一个'void main()'是C ++标准直接不允许的,尽pipe没有任何事情可以阻止一个非标准的实现允许替代。

共同扩展

Unix系统经典地支持第三个变体:

 int main(int argc, char **argv, char **envp) { ... } 

第三个参数是一个以空字符结尾的指向string的指针列表,每个指针都是一个具有名称,等号和值(可​​能为空)的环境variables。 如果你不使用这个,你仍然可以通过' extern char **environ; '来获得extern char **environ; ”。 很长一段时间,它没有声明它的头文件,但POSIX 2008标准现在要求在<unistd.h>声明它。

这被C标准认为是一个通用的扩展,logging在附件J中:

J.5.1环境参数

¶1在托pipe环境中,主函数接收第三个参数char *envp[] ,该参数指向一个以char为空的终止指针数组,每个指向一个string,该string提供有关此执行的环境的信息(5.1.2.2.1)。

微软C

Microsoft VS 2010编译器很有趣。 该网站说:

main的声明语法是

  int main(); 

或者可选地,

 int main(int argc, char *argv[], char *envp[]); 

或者, mainwmain函数可以被声明为返回void (无返回值)。 如果将mainwmain声明为返回void,则不能使用return语句将退出代码返回到父进程或操作系统。 要将mainwmain声明为void时返回一个退出代码,您必须使用exit函数。

当有一个带有void main()的程序确实退出时,我不清楚发生了什么(退出代码返回给父类或o / s),而且MS网站也是无声的。

有趣的是,MS并没有规定C和C ++标准要求的main()的双参数版本。 它只规定了三个参数的forms,其中第三个参数是char **envp ,一个指向环境variables列表的指针。

微软的网页还列出了一些其他的select – wmain()需要宽字符string,还有一些。

本页面的Microsoft VS 2005版本没有列出void main()作为替代。 从微软VS 2008开始的版本呢 。

http://en.wikipedia.org/wiki/Main_function_(programming)#C_and_C.2B.2B

除了通常的int main(int argc, char *argv[])和POSIX int main(int argc, char **argv, char **envp) ,Mac OS X还支持

 int main(int argc, char* argv[], char* envp[], char* apple[]); 

当然,这只是Mac。

在Windows上

 int wmain(int argc, wchar_t* argv[], wchar_t* envp[]); 

作为Unicode(实际上是宽字符)变体。 当然也有WinMain

 int main(void) 

在某些操作系统下(例如Windows)也是这样的:

 int main(int argc, char **argv, char **envp) 

envp给出了一个环境,否则通过getenv()