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

问题描述 投票:52回答:5

C中主要功能的有效签名究竟是什么?我知道:

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

还有其他有效的吗?

c language-lawyer signature entry-point function-prototypes
5个回答
63
投票

本回答(C11)时的现行标准明确提到了这两个:

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

虽然它确实提到了“或等同”这一短语,但附有以下脚注:

因此,int可以被定义为typedefint名称替换,或者argv的类型可以被写为char ** argv,依此类推。

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

相关部分(C11中的第5.1.2.2.1节,但此特定方面与C99相同)说明:

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

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

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

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

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

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

  • argc的值应为非负值。
  • argv[argc]应为空指针。
  • 如果argc的值大于零,则数组成员argv[0]argv[argc-1]包含指向字符串的指针,这些指针在程序启动之前由主机环境给出实现定义的值。目的是在程序启动之前从托管环境中的其他地方向程序提供信息。如果主机环境不能提供大写和小写字母的字符串,则实现应确保以小写形式接收字符串。
  • 如果argc的值大于零,则argv[0]指向的字符串表示程序名称;如果程序名不能从主机环境获得,则argv[0][0]应为空字符。如果argc的值大于1,则argv[1]通过argv[argc-1]指向的字符串表示程序参数。
  • 参数argcargv以及argv数组指向的字符串应该可由程序修改,并在程序启动和程序终止之间保留它们最后存储的值。

请注意,这适用于托管环境,您通常在C程序中看到的环境。独立环境(例如嵌入式系统)的约束要少得多,如同标准的5.1.2.1中所述:

在独立环境中(可以在没有操作系统任何好处的情况下执行C程序),程序启动时调用的函数的名称和类型是实现定义的。除了第4章要求的最小集合之外,任何可用于独立程序的库设施都是实现定义的。


13
投票

标准C.

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

5.1.2.2.1 Program startup

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

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

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

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

或等效的; 9)或其他一些实施定义的方式。

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

C11和C18标准与C99标准基本相同。

标准C ++

C ++ 98标准说:

3.6.1 Main function [basic.start.main]

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

2实现不应预定义主要功能。此功能不应过载。它应具有int类型的返回类型,否则其类型是实现定义的。所有实现都应允许以下两个主要定义:

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

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

C ++标准明确地说“它[主函数]应该具有int类型的返回类型,但是其类型是实现定义的”,并且需要与C标准相同的两个签名。因此,C ++标准直接不允许'void main()',尽管没有什么可以阻止非标准的符合实现允许替代(也不是标准的符合实现允许替代作为标准的扩展)。

C ++ 03,C ++ 11,C ++ 14和C ++ 17标准与C ++ 98基本相同。

共同扩展

传统上,Unix系统支持第三种变体:

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

第三个参数是一个以null结尾的字符串指针列表,每个字符串都是一个环境变量,它有一个名称,一个等号和一个值(可能是空的)。如果你不使用它,你仍然可以通过'extern char **environ;'进入环境。很长一段时间,它没有声明它的标题,但POSIX 2008标准现在要求它在<unistd.h>中声明。

这被C标准认可为附录J中记录的共同扩展:

J.5.1 Environment arguments

¶1在托管环境中,main函数接收第三个参数char *envp[],该参数指向以null结尾的指向char的指针数组,每个指针都指向一个字符串,该字符串提供有关此程序执行环境的信息( 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()的双参数版本。它只规定了一个三参数形式,其中第三个参数是char **envp,一个指向环境变量列表的指针。

微软页面还列出了一些其他选择 - wmain(),它采用宽字符串,还有更多。

Microsoft VS 2005版本的this page没有列出void main()作为替代方案。来自Microsoft VS 2008的versions确实如此。

int main()int main(void)一样吗?

有关详细分析,请参阅我对What should main() return in C and C++的回答结束。 (似乎我曾经认为这个问题提到了C ++,尽管它没有,也从来没有。在C ++中,int main()int main(void)之间没有区别,int main()是惯用的C ++。)

在C中,两种符号之间存在差异,但您只能在深奥的情况下注意到它。具体来说,如果你从你自己的代码中调用main()函数就会有所不同,你可以在C中调用它并且不允许在C ++中执行。

int main()表示法没有为main()提供原型,但这只有在你递归调用时才有意义。使用int main(),您可能稍后(在同一个函数中,或在另一个函数中)编写int rc = main("absolute", "twaddle", 2):,并且正式编译器不应该抱怨拒绝编译代码,尽管它可能合法地抱怨(警告你)它(和使用带有GCC的-Werror会将警告转换为错误)。如果你使用int main(void),随后对main()的调用应该会产生一个错误 - 你说该函数没有参数,但试图提供三个。当然,在声明或定义它之前,你不能合法地调用main()(除非你仍在使用C90语义) - 并且实现没有声明main()的原型。注意:C11标准在不同的例子中说明了int main()int main(void) - 两者在C中都有效,即使它们之间存在细微差别。


8
投票

POSIX支持execve(),而int main(int argc, char *argv[], char *envp[]) 又支持

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

添加的参数是环境,即NAME = VALUE形式的字符串数组。


8
投票

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

除了通常的int main(int argc, char **argv, char **envp)和POSIX int main(int argc, char* argv[], char* envp[], char* apple[]); 之外,在Mac OS X上也支持

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

当然它只是Mac版。

在Windows上有

WinMain

作为Unicode(实际上是宽字符)变体。当然还有int main(void)


2
投票
int main(int argc, char **argv, char **envp)

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

envp

其中getenv()提供了一个环境,否则可以通过qazxswpoi访问

© www.soinside.com 2019 - 2024. All rights reserved.