What should main() return in C and C++?
什么是正确的(最有效的)方法来定义EDCOX1 0函数在C和C++ +EDCOX1中1函数或
这个问题有许多副本,包括:
- C的
main() 函数的有效签名是什么? main() 函数的返回类型void main() 和int main() 的区别?- C++中EDCOX1的0位签名
main() 的正确声明是什么?-对于C++,确实有很好的答案。- c中
main() 函数的样式 - c中
main() 方法的返回类型 - c中
int main() 与void main() 的比较
相关:
- C++EDCOX1〔16〕
- C++EDCOX1〔17〕
char *envp[] 是main() 可移植的第三个参数吗?int main() 函数必须在所有编译器中返回值吗?- 为什么EDCOX1的0个函数在C和C++中的类型留给用户定义?
- 为什么
int main(){} 编译? - EDCOX1第0条在C++ 14中的法律定义
EDOCX1的返回值(0)应该指示程序如何退出。正常退出通常由来自
1 | int main() |
和
1 | int main(int argc, char* argv[]) |
相当于
1 | int main(int argc, char** argv) |
同样值得注意的是,在C++中,EDCOX1×4可不带返回语句,此时默认为返回0。这也适用于C99程序。是否应省略
此外,效率不是
接受的答案似乎是针对C++的,所以我想我会添加一个与C有关的答案,这在一些方面是不同的。
ISO/IEC 9899:1989(C90):
1 2 | int main(void) int main(int argc, char **argv) |
或等同的。例如,
如果一个实现允许,可以用其他方式声明
该标准定义了3个严格符合的返回值(即不依赖于实现定义的行为):成功终止的
最后,从标准的角度来看,从程序调用
ISO/IEC 9899:1999(C99):
对于C99,除了:
- 不能省略
int 返回类型。 - 您可以省略
main() 中的返回语句。如果你这样做了,并且main() 完成了,那么有一个隐含的return 0 。
标准C-托管环境
对于托管环境(这是正常环境),C11标准(ISO/IEC 9899:2011)表示:好的。
5.1.2.2.1 Program startup
The function called at program startup is named
main . The implementation declares no
prototype for this function. It shall be defined with a return type ofint and with no
parameters:Ok.
1 int main(void) { /* ... */ }or with two parameters (referred to here as
argc andargv , though any names may be
used, as they are local to the function in which they are declared):Ok.
1 int main(int argc, char *argv[]) { /* ... */ }or equivalent;10) or in some other implementation-defined manner.
Ok.
If they are declared, the parameters to the main function shall obey the following
constraints:Ok.
- The value of
argc shall be nonnegative.argv[argc] shall be a null pointer.- If the value of
argc is greater than zero, the array membersargv[0] through
argv[argc-1] inclusive shall contain pointers to strings, which are given
implementation-defined values by the host environment prior to program startup. The
intent is to supply to the program information determined prior to program startup
from elsewhere in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the implementation
shall ensure that the strings are received in lowercase.- If the value of
argc is greater than zero, the string pointed to byargv[0]
represents the program name;argv[0][0] shall be the null character if the
program name is not available from the host environment. If the value ofargc is
greater than one, the strings pointed to byargv[1] throughargv[argc-1]
represent the program parameters.- The parameters
argc andargv and the strings pointed to by theargv array shall
be modifiable by the program, and retain their last-stored values between program
startup and program termination.10) Thus,
int can be replaced by a typedef name defined asint , or the type ofargv can be written as
char **argv , and so on.Ok.
C99或C11中的程序终止
从
1如果
11)根据6.2.4,
请注意,
在C89中(因此在Microsoft C中),没有关于如果
7.22.4.4 The
exit function?5 Finally, control is returned to the host environment. If the value of
status is zero orEXIT_SUCCESS , an implementation-defined form of the status successful termination is returned. If the value ofstatus isEXIT_FAILURE , an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.Ok.
标准C++环境
C++ 11标准(ISO/IEC 1488∶2011)表示:好的。< Buff行情>3.6.1主要功能[基本.开始.主要]
?1程序应包含一个称为main的全局函数,该函数是程序的指定开始。[…]好的。
?(二)实施前不得预先确定主要功能。此功能不得过载。它应该具有int类型的返回类型,但其类型是实现定义的。所有实现应允许以下两种主要定义:好的。
1 | int main() { /* ... */ } |
和好的。
1 | int main(int argc, char* argv[]) { /* ... */ } |
在后一种形式中,
?3.程序中不得使用函数
?5.主返回语句具有离开主功能(自动销毁任何对象)的效果并以返回值为参数调用
1 | return 0; |
< /块引用>
C++标准明确地表示:"它(main函数)应该具有返回类型的EDCOX1×0),但它的类型是实现定义的,并且需要与C标准相同的两个签名作为选项来支持。因此,"空主机"()不被C++标准所允许,尽管它没有什么可以阻止非标准实现允许替代。请注意,C++禁止用户调用EDCOX1×1Ω(但C标准不)。好的。
在C++ 11标准中,有一段省略的18.5开始和终止,它与来自C7.11标准(上面引用的)中EDCOX1×2函数的段落相同,除了脚注(简单地说明EDOCX1 3)和EDCOX1(4)在EDCOX1(5)中定义。好的。标准C-通用扩展
传统上,Unix系统支持第三种变体:好的。
1 | int main(int argc, char **argv, char **envp) { ... } |
第三个参数是以空结尾的字符串指针列表,每个指针都是一个环境变量,具有名称、等号和值(可能为空)。如果您不使用它,您仍然可以通过"EDOCX1"(6)访问环境。很长一段时间以来,它没有声明它的头文件,但是POSIX2008标准现在要求它在
C标准承认这是一种常见的扩展,记录在附录J中:好的。
J.5.1 Environment arguments
?1 In a hosted environment, the main function receives a third argument,
char *envp[] ,
that points to a null-terminated array of pointers tochar , each of which points to a string
that provides information about the environment for this execution of the program (5.1.2.2.1).Ok.
微软C
Microsoft vs 2010编译器很有趣。网站上说:好的。
The declaration syntax for main is
Ok.
1 int main();or, optionally,
Ok.
1 int main(int argc, char *argv[], char *envp[]);Alternatively, the
main andwmain functions can be declared as returningvoid (no return value). If you declaremain orwmain as returning void, you cannot return an exit code to the parent process or operating system by using a return statement. To return an exit code whenmain orwmain is declared asvoid , you must use theexit function.Ok.
我不清楚当带有
有趣的是,MS并没有规定C和C++标准要求的EDCOX1 9的两个参数版本。它只规定了三参数形式,其中第三个参数是
微软页面还列出了一些其他的替代方案,比如需要宽字符串的
此页的Microsoft Visual Studio 2005版本没有将
如前所述,上述要求适用于托管环境。如果您使用的是独立环境(这是托管环境的替代方案),那么该标准就没有什么可说的了。对于独立环境,在程序启动时调用的函数不需要调用
5.1.2 Execution environments
Two execution environments are defined: freestanding and hosted. In both cases,
program startup occurs when a designated C function is called by the execution
environment. All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified. Program termination returns control to the execution environment.Ok.
5.1.2.1 Freestanding environment
In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined. Any library facilities available to a freestanding program, other than the minimal set required by clause 4, are implementation-defined.
Ok.
The effect of program termination in a freestanding environment is implementation-defined.
Ok.
交叉引用第4条一致性是指:好的。< Buff行情>
?5.严格符合标准的程序只能使用本国际标准中规定的语言和库的特性。3)不得根据任何未规定、未定义或实施定义的行为产生输出,也不得超过任何最低实施限制。好的。
?6两种形式的一致性实施是独立的和独立的。符合要求的托管实施应接受任何严格符合要求的方案。一致性独立实施应接受任何严格一致的程序,其中,图书馆条款(第7条)中规定的功能的使用仅限于标准标题
?符合性计划是符合性实施可接受的计划。5)好的。
3)严格一致的程序可以使用条件特征(见6.10.8.3),前提是使用相关宏的适当条件包含预处理指令来保护使用。例如:好的。
1 2 3 4 5 | #ifdef __STDC_IEC_559__ /* FE_UPWARD defined */ /* ... */ fesetround(FE_UPWARD); /* ... */ #endif |
4)这意味着一致性实施不保留除本国际标准明确保留的标识符以外的任何标识符。好的。
5)严格符合性程序旨在在符合性实施中最大限度地可移植。一致性程序可能依赖一致性实现的不可移植特性。好的。< /块引用>
值得注意的是,独立环境中实际定义任何函数所需的唯一头文件是
正如C标准认可托管环境和独立环境一样,C++标准也是如此。(引用自ISO/IEC 14882:2011。)好的。< Buff行情>1.4执行合规性[简介合规性]
?7定义了两种实现:托管实现和独立实现。对于托管实现,此国际标准定义了一组可用的库。独立式的实现是在不借助操作系统的情况下执行操作的一种方式,它具有一组由实现定义的库,其中包括某些语言支持库(17.6.1.3)。好的。
?8一致性实现可以有扩展(包括附加的库函数),前提是它们不会改变任何格式良好的程序的行为。需要实现来诊断那些使用不符合本国际标准的扩展。然而,这样做之后,他们就可以编译和执行这样的程序。好的。
?9每个实现都应包含文档,用于标识其不支持的所有有条件支持的构造,并定义所有特定于区域设置的特征。3好的。
3)本文件还定义了实施定义的行为;见1.9。好的。17.6.1.3独立实施[符合性]
定义了两种实现:托管和独立(1.4)。对于托管实现,此国际标准描述了一组可用的头。好的。
独立的实现具有一组实现定义的头。该组至少应包括表16所示的标题。好的。
提供的报头
表16——独立实现的C++标题好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 | Subclause Header(s) <ciso646> 18.2 Types <cstddef> 18.3 Implementation properties <cfloat> <limits> <climits> 18.4 Integer types <cstdint> 18.5 Start and termination <cstdlib> 18.6 Dynamic memory management <new> 18.7 Type identification <typeinfo> 18.8 Exception handling <exception> 18.9 Initializer lists <initializer_list> 18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool> 20.9 Type traits <type_traits> 29 Atomics |
< /块引用>在C中使用
C11标准的标准§5.1.2.2.1显示了首选的符号——
6.5.3.4 The
sizeof and_Alignof operators…
Ok.
?8 EXAMPLE 3 In this example, the size of a variable length array is computed and returned from a function:
Ok.
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}
好啊。
我认为,
注意,C和C++标准定义了两种实现:独立式和托管式。好的。
C90托管环境好的。
允许的表单1:好的。
1
2
3
4
5
6int main (void)
int main (int argc, char *argv[])
main (void)
main (int argc, char *argv[])
/*... etc, similar forms with implicit int */评论:好的。
前两个被显式地声明为允许的形式,其他的被隐式地允许,因为c90允许"隐式int"用于返回类型和函数参数。不允许使用其他形式。好的。
C90独立式环境好的。
任何形式或名称的主要允许2。好的。
C99托管环境好的。
允许的表单3:好的。
1
2
3int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */评论:好的。
c99删除了"隐式int",因此
main() 不再有效。好的。引入了一个奇怪的、模棱两可的句子"或以其他实现定义的方式"。这可以解释为"
int main() 的参数可能会变化"或"main可以有任何实现定义的形式"。好的。有些编译器选择用后一种方式解释标准。有争议的是,人们不能轻易地通过引用标准本身来说明它们不严格符合标准,因为标准本身是模棱两可的。好的。
然而,允许完全野生形式的
main() 可能是(?)不是这个新句子的意思。c99基本原理(非规范性)意味着该句是指int main 4的附加参数。好的。然而,托管环境程序终止部分继续讨论main不返回int 5的情况。尽管该部分不规范如何声明main,但它明确意味着可以以完全实现定义的方式声明main,即使在托管系统上也是如此。好的。
C99独立式环境好的。
任何形式或名称的主要允许6。好的。
C11托管环境好的。
允许的表单7:好的。
1
2
3int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */C11独立式环境好的。
任何形式或名称的主允许8。好的。
请注意,
6.11.6 Function declarators
Ok.
The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.
Ok.
C++ 03托管环境好的。
允许的表单9:好的。
1
2int main ()
int main (int argc, char *argv[])评论:好的。
注意第一个形式中的空括号。C++和C在这种情况下是不同的,因为在C++中这意味着函数不需要参数。但在C语言中,它意味着它可以接受任何参数。好的。
C++ 03独立环境好的。
启动时调用的函数名是实现定义的。如果命名为
main() ,则必须遵循规定的格式10:好的。1
2
3// implementation-defined name, or
int main ()
int main (int argc, char *argv[])C++ 11托管环境好的。
允许的表格11:好的。
1
2int main ()
int main (int argc, char *argv[])评论:好的。
该标准的文本已更改,但其含义相同。好的。
C++ 11独立环境好的。
启动时调用的函数名是实现定义的。如果命名为
main() ,则必须遵循规定的格式12:好的。1
2
3// implementation-defined name, or
int main ()
int main (int argc, char *argv[])
工具书类好的。
ANSI X3.159-1989 2.1.2.2托管环境。"程序启动"好的。
The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:Ok.
1 | int main(void) { /* ... */ } |
or with two parameters (referred to here as
argc and argv, though any names may be used, as they are local to the
function in which they are declared):Ok.
1 | int main(int argc, char *argv[]) { /* ... */ } |
ANSI X3.159-1989 2.1.2.1独立环境:好的。
In a freestanding environment (in which C program execution may take
place without any benefit of an operating system), the name and type
of the function called at program startup are implementation-defined.Ok.
ISO 9899:1999 5.1.2.2托管环境->5.1.2.2.1程序启动好的。
The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:Ok.
1 | int main(void) { /* ... */ } |
or with two parameters (referred to here as
argc and argv, though any names may be used, as they are local to the
function in which they are declared):Ok.
1 | int main(int argc, char *argv[]) { /* ... */ } |
or equivalent;9) or in some other implementation-defined
manner.Ok.
国际标准-程序设计语言-C的基本原理,第5.10版。5.1.2.2托管环境——>5.1.2.2.1程序启动好的。< Buff行情>
主参数的行为,以及退出、主和不退出的交互作用。(见§7.20.4.2)已编纂成法典,以抑制ARGV代表中的一些不必要的变化。字符串,以及由main返回的值的含义。好的。
argc和argv作为主参数的规范承认了广泛的先验实践。argv[argc]必须是一个空指针,以便在常规实践的基础上为列表的结尾提供冗余检查。好的。
main是唯一可以用零个或两个参数声明的可移植函数。(其他函数的参数数目必须在调用和定义之间完全匹配。)这种特殊的情况只是认识到当程序不访问程序参数字符串时,将参数留给MAIN的广泛实践。虽然许多实现支持两个以上的主参数,但标准既不祝福也不禁止这种实践;用三个参数定义主参数的程序并不严格符合标准(见§J.5.1)。好的。< /块引用>
ISO 9899:1999 5.1.2.2托管环境——>5.1.2.2.3程序终止好的。
If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument;11) reaching the
} that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.Ok.
ISO 9899:1999 5.1.2.1独立式环境好的。
In a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined.
Ok.
ISO 9899:2011 5.1.2.2托管环境->5.1.2.2.1程序启动好的。
本节与上面引用的C99相同。好的。
ISO 9899:1999 5.1.2.1独立式环境好的。
本节与上面引用的C99相同。好的。
ISO 14882:2003 3.6.1主要功能好的。
An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main:
Ok.
1 | int main() { /* ... */ } |
and
Ok.
1 | int main(int argc, char* argv[]) { /* ... */ } |
ISO 14882:2003 3.6.1主要功能好的。
It is implementation-defined whether a program in a freestanding environment is required to define a main function.
Ok.
ISO 14882:2011 3.6.1主要功能好的。
An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall
allow bothOk.
— a function of () returning int and
Ok.
— a function of (int, pointer to pointer to char) returning int
Ok.
as the type of main (8.3.5).
Ok.
ISO 14882:2011 3.6.1主要功能好的。
本节与上面引用的C++ 03相同。好的。
好啊。
成功时返回0,错误时返回非零。这是Unix和DOS脚本使用的标准,用于找出程序发生了什么。
c89和k&r c中的
1 | return 1? return 0? |
如果您不在
父进程将接收
看看我怎样才能得到我的主函数返回了什么?.
1 2 | $ ./a.out $ echo $? |
这样就可以看出,它是一个变量
在UNIX和DOS脚本中,成功时返回
请记住,即使返回int,一些OSE(Windows)也会将返回的值截断为单字节(0-255)。
操作系统可以使用返回值来检查程序是如何关闭的。
在大多数操作系统中,返回值0通常意味着OK(我无论如何都能想到)。
当您自己调用一个进程时,也可以检查它,并查看程序是否退出并正确完成。
这不仅仅是一个编程约定。
返回0应告知程序员程序已成功完成作业。
我的印象是,Standard指定main不需要返回值,因为成功的返回是基于OS的(一个中的零可能是成功的,另一个中的零可能是失败的),因此缺少返回是编译器插入成功返回本身的提示。
但是我通常返回0。
如果确实存在与从进程返回整数的效率相关的问题,那么您可能应该避免多次调用该进程,使该返回值成为问题。
如果您这样做(多次调用一个进程),您应该找到一种方法,将您的逻辑直接放入调用方或一个dll文件中,而不为每个调用分配一个特定的进程;在这种情况下,多进程分配会给您带来相关的效率问题。
详细地说,如果您只想知道返回0的效率是否高于或低于返回1的效率,在某些情况下,它可能依赖于编译器,但一般来说,假设它们是从同一个源(本地、字段、常量、嵌入到代码中、函数结果等)读取的,则需要完全相同的时钟周期数。
What is the correct (most efficient) way to define the main() function in C and C++ — int main() or void main() — and why?
那些词(最有效的)不会改变问题。除非你是在一个独立的环境中,否则有一个普遍正确的方法来声明
What should
main() return in C and C++?
这不是
If int main() then return 1 or return 0?
0表示成功,非0表示失败。同样,这不是你需要(或得到)选择的东西:它是由你应该遵守的接口定义的。
返回什么取决于您想对可执行文件做什么。例如,如果将程序与命令行shell一起使用,则需要返回0表示成功,返回非零表示失败。然后,根据代码的结果,您将能够使用shell中的程序进行条件处理。此外,您还可以根据您的解释分配任何非零值,例如,对于严重错误,不同的程序退出点可以终止具有不同退出值的程序,调用shell可以使用这些值来决定通过检查返回的值要做什么。如果代码不打算与shell一起使用,并且返回的值不会影响任何人,那么它可能会被省略。我个人使用签名
这里是一个关于返回码用法的小演示…
当使用Linux终端提供的各种工具时,可以使用返回代码,例如在进程完成后进行错误处理。假设存在以下文本文件myfile:
This is some example in order to check how grep works.
执行grep命令时,会创建一个进程。一旦它通过(并且没有中断),它将返回一些介于0和255之间的代码。例如:
1 | $ grep order myfile |
如果你这样做了
1 2 | $ echo $? $ 0 |
您将获得0。为什么?因为grep找到一个匹配项并返回一个退出代码0,这是成功退出的通常值。让我们再次检查一下,但是有一些东西不在我们的文本文件中,因此不会找到匹配项:
1 2 3 | $ grep foo myfile $ echo $? $ 1 |
由于grep未能将标记"foo"与我们文件的内容匹配,返回代码为1(这是发生故障时的常见情况,但如上所述,您有许多值可供选择)。
现在,下面的bash脚本(只需在Linux终端中键入)虽然非常基本,但应该给出一些错误处理的概念:
1 2 3 4 5 | $ grep foo myfile $ CHECK=$? $ [ $CHECK -eq 0] && echo 'Match found' $ [ $CHECK -ne 0] && echo 'No match was found' $ No match was found |
在第二行之后,由于"foo"使grep返回1,所以没有任何内容打印到终端,我们检查grep的返回代码是否等于0。第二个条件语句在最后一行中回显其消息,因为由于check==1,它是真的。
正如您所看到的,如果您正在调用这个和那个进程,那么有时必须查看它返回了什么(通过main()的返回值)。
省略EDOCX1[0]
当C或C++程序到达EDOCX1的结尾时,编译器1将自动生成代码返回0,因此不需要在EDCOX1 1的结尾显式地放置EDOCX1 2。
注:当我提出这个建议时,几乎总是紧接着两种评论中的一种:"我不知道。"或者"这是个坏建议!"我的理由是,依赖标准显式支持的编译器行为是安全和有用的。对于c,自c99;见ISO/IEC 9899:1999第5.1.2.2.3节:
[...] a return from the initial call to the
main function is equivalent to calling theexit function with the value returned by themain function as its argument; reaching the} that terminates themain function returns a value of 0.
对于C++,由于第一个标准为1998;参见ISO/IEC 1488∶1998第3.3.1节:
If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;
此后两种标准的所有版本(C99和C++ 98)都保持了相同的想法。我们依赖于C++中自动生成的成员函数,很少有人在EDCOX1×5函数的结尾写显式的EDCOX1×4个语句。反对省略的理由似乎归结为"看起来很奇怪"。如果你和我一样,对改变C标准的理由感到好奇,请阅读这个问题。另请注意,在20世纪90年代初,这被认为是"草率的做法",因为当时它是未定义的行为(尽管受到广泛支持)。
所以我主张省略它;其他人则不同意(通常是激烈的!)在任何情况下,如果您遇到忽略它的代码,您将知道它是由标准显式支持的,并且您将知道它的含义。
在C++中,main函数应该声明为int main(),而不是空虚main(),因为编译器在空格main的情况下抛出一个错误。主函数可以接受任何数量的参数,如int main(int k、int l、int arr[])或int main(void)。
1 2 3 4 5 6 7 8 | #include <iostream> using namespace std; int main(void) { // your code goes here cout<<"a"; return 0; } |
输出:
1 2 | Success #stdin #stdout 0s 4416KB a |
返回部分只返回0,否则编译器将抛出错误。例如,如果返回1,将获得所需的输出,但它也会引发运行时错误。
例子
1 2 3 4 5 6 7 8 9 10 11 12 | #include <iostream> using namespace std; int main(int k,float m,char g, int arr[]) { // your code goes here k=0; cout<<k; g='a'; cout<<g; cout<<"a"; return 1; } |
输出:
1 2 | Runtime error #stdin #stdout 0s 4448KB 0aa |