C 的 main() 函数的有效签名是什么?
C 中 main 函数的有效签名到底是什么?我知道:
int main(int argc, char *argv[])
还有其他有效的吗?
What really are the valid signatures for main function in C? I know:
int main(int argc, char *argv[])
Are there other valid ones?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
C11
标准明确提到了这两个:尽管它确实提到了短语“或等效项”并带有以下脚注:
此外,它还提供了更多(实现定义的)可能性。
相关文本(
5.1.2.2.1
节,但这一特定方面与C99
相比没有变化)指出:请注意,这是针对托管环境,即您通常在 C 程序中看到的环境。独立环境(例如嵌入式系统)受到的限制要少得多,如同一标准的
5.1.2.1
中所述:The
C11
standard explicitly mentions these two:although it does mention the phrase "or equivalent" with the following footnote:
In addition, it also provides for more (implementation-defined) possibilities.
The relevant text (section
5.1.2.2.1
, but this particular aspect is unchanged fromC99
) states:Note that this is for a hosted environment, the ones you normally see in C programs. A free-standing environment (such as an embedded system) is far less constrained, as stated in
5.1.2.1
of that same standard:标准 C
对于托管环境(这是正常的环境),C99 标准规定:
C11和C18标准与C99标准基本相同。
标准 C++
C++98 标准规定:
C++ 标准明确表示“它 [主函数] 应具有
int
类型的返回类型,但否则其类型是实现定义的”,并且要求与 C 标准相同的两个签名。因此,C++ 标准直接不允许“void main()”,尽管它无法阻止非标准一致性实现允许替代方案(也无法阻止标准一致性实现允许替代方案作为标准的扩展)。C++03、C++11、C++14 和 C++17 标准与 C++98 基本相同。
公共扩展
经典上,Unix 系统支持第三种变体:
第三个参数是一个以 null 结尾的字符串指针列表,每个字符串都是一个环境变量,有一个名称、一个等号和一个值(可能为空)。如果您不使用它,您仍然可以通过“
extern char **environ;
”获取环境。该变量(仍然)未在任何 POSIX 标头中声明(尽管有此答案的先前版本)。这被 C 标准认可为通用扩展,记录在附录 J 中:
Microsoft C
Microsoft VS 2010 编译器很有趣。该网站说:
我不清楚当带有
void main()
的程序退出时会发生什么(什么退出代码返回给父级或操作系统)——并且 MS 网站也保持沉默。有趣的是,MS 并没有规定 C 和 C++ 标准所要求的
main()
的双参数版本。它只规定了三参数形式,其中第三个参数是 char **envp,指向环境变量列表的指针。Microsoft 页面还列出了一些其他替代方案 -
wmain()
(它采用宽字符字符串)等等。此页面的 Microsoft VS 2005 版本 没有列出
void main()
作为替代方案。 Microsoft VS 2008 及以后的版本做。int main()
与int main(void)
相同吗?有关详细分析,请参阅我对 在 C 和 C++ 中
main()
应该返回什么。 (似乎我曾经认为这个问题提到了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 中都是有效的,尽管它们之间存在细微的差异。Standard C
For a hosted environment (that's the normal one), the C99 standard says:
The C11 and C18 standards say essentially the same as the C99 standard.
Standard C++
The C++98 standard says:
The C++ standard explicitly says "It [the main function] shall have a return type of type
int
, but otherwise its type is implementation defined", and requires the same two signatures as the C standard. So a 'void main()' is directly not allowed by the C++ standard, though there's nothing it can do to stop a non-standard conforming implementation from allowing alternatives (nor a standard conforming implementation from allowing alternatives as extensions to the standard).The C++03, C++11, C++14, and C++17 standards say essentially the same as C++98.
Common Extension
Classically, Unix systems support a third variant:
The third argument is a null-terminated list of pointers to strings, each of which is an environment variable which has a name, an equals sign, and a value (possibly empty). If you do not use this, you can still get at the environment via '
extern char **environ;
'. This variable is (still) not declared in any POSIX header (previous versions of this answer notwithstanding).This is recognized by the C standard as a common extension, documented in Annex J:
Microsoft C
The Microsoft VS 2010 compiler is interesting. The web site says:
It is not clear to me what happens (what exit code is returned to the parent or o/s) when a program with
void main()
does exit — and the MS web site is silent too.Interestingly, MS does not prescribe the two-argument version of
main()
that the C and C++ standards require. It only prescribes a three-argument form where the third argument ischar **envp
, a pointer to a list of environment variables.The Microsoft page also lists some other alternatives —
wmain()
which takes wide-character strings, and some more.The Microsoft VS 2005 version of this page does not list
void main()
as an alternative. The versions from Microsoft VS 2008 onwards do.Is
int main()
the same asint main(void)
?For a detailed analysis, see the end of my answer to What should
main()
return in C and C++. (It seems that I once considered that this question referred to C++, even though it doesn't and never did. In C++, there is no difference betweenint main()
andint main(void)
andint main()
is idiomatic C++.)In C, there is a difference between the two notations, but you only notice it in esoteric cases. Specifically, there's a difference if you call the
main()
function from your own code, which you're allowed to do in C and are not allowed to do in C++.The
int main()
notation does not provide a prototype formain()
, but that only matters if you call it recursively. Withint main()
, you might later (in the same function, or in another function) writeint rc = main("absolute", "twaddle", 2):
and formally the compiler shouldn't complain to the extent of refusing to compile the code, though it might legitimately complain (warn you) about it (and using-Werror
with GCC would convert the warning into an error). If you useint main(void)
, the subsequent call tomain()
should generate an error — you said the function takes no arguments but tried to provide three. Of course, you can't legitimately callmain()
before you've declared or defined it (unless you are still using C90 semantics) — and the implementation does not declare a prototype formain()
. NB: The C11 standard illustrates bothint main()
andint main(void)
in different examples — both are valid in C, even though there's the subtle difference between them.POSIX 支持
execve()
,它反过来支持添加的参数是环境,即形式为 NAME=VALUE 的字符串数组。
POSIX supports
execve()
, which in turn supportsThe added argument is the environment, i.e. an array of strings of the form NAME=VALUE.
http://en.wikipedia.org/wiki/Main_function_(programming) #C_and_C.2B.2B
除了通常的
int main(int argc, char *argv[])
和 POSIXint main(int argc, char **argv, char **envp)
,在 Mac OS X 上也支持,当然它仅限于 Mac。
在 Windows 上有
Unicode(实际上是宽字符)变体。当然还有
WinMain
。http://en.wikipedia.org/wiki/Main_function_(programming)#C_and_C.2B.2B
Besides the usual
int main(int argc, char *argv[])
and the POSIXint main(int argc, char **argv, char **envp)
, on Mac OS X also supportsOf course it's Mac-only.
On Windows there's
as the Unicode (actually, wide-character) variant. Of course there is
WinMain
too.在某些操作系统(例如 Windows)下,这也是有效的:
其中
envp
提供一个环境,否则可以通过getenv()
访问Under some OS (for example, Windows) also such is valid:
where
envp
gives an environment, otherwise accessible throughgetenv()