795

main()在 C 和 C++中定义函数的正确(最有效)方法是什么——int main()或者void main()——为什么?论点又如何?如果int main()那么return 1return 0


这个问题有很多重复,包括:

有关的:

4

18 回答 18

643

的返回值main指示程序如何退出。正常退出由 0 返回值表示main。非零返回表示异常退出,但对于如何解释非零代码没有标准。正如其他人所指出的,void main()C++ 标准禁止使用,不应使用。有效的 C++main签名是:

int main()

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

这相当于

int main(int argc, char** argv)

还值得注意的是,在 C++ 中,int main()可以不使用返回语句,此时默认返回 0。对于 C99 程序也是如此。是否return 0;应该省略还有待商榷。有效的 C 程序主签名的范围要大得多。

效率不是main功能的问题。根据 C++ 标准,它只能进入和离开一次(标记程序的开始和终止)。对于 C,允许重新输入main(),但应避免。

于 2008-10-15T12:16:08.277 回答
204

接受的答案似乎是针对 C++ 的,所以我想我会添加一个与 C 相关的答案,这在几个方面有所不同。ISO/IEC 9899:1989 (C90) 和 ISO/IEC 9899:1999 (C99) 之间也有一些变化。

main()应声明为:

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

或同等学历。例如,int main(int argc, char *argv[])相当于第二个。在 C90 中,int返回类型可以省略,因为它是默认值,但在 C99 和更高版本中,int返回类型不能省略。

如果实现允许,main()可以用其他方式声明(例如,int main(int argc, char *argv[], char *envp[])),但这会使程序实现定义,并且不再严格符合。

该标准定义了 3 个严格符合的返回值(即不依赖于实现定义的行为):成功终止和0不成功终止。任何其他值都是非标准的和实现定义的。在 C90 中,必须在末尾有一个显式语句以避免未定义的行为。在 C99 和更高版本中,您可以省略. 如果你这样做了,并且完成了,就会有一个隐含的.EXIT_SUCCESSEXIT_FAILUREmain()returnmain()main()return 0

最后,从标准的角度来看,从 C 程序main() 递归调用并没有错。

于 2008-10-16T09:59:57.177 回答
137

标准 C — 托管环境

对于托管环境(这是正常环境),C11 标准 (ISO/IEC 9899:2011) 说:

5.1.2.2.1 程序启动

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

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

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

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

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

如果它们被声明,主函数的参数应遵守以下约束:

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

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

C99 或 C11 中的程序终止

从返回的值main()以实现定义的方式传输到“环境”。

5.1.2.2.3 程序终止

1 如果main函数的返回类型是与 兼容的类型int,则从函数的初始调用返回main相当于以exit函数返回的值main作为参数调用函数;11)到达}终止 main函数返回值0。如果返回类型与 不兼容int,则返回到宿主环境的终止状态未指定。

11)根据 6.2.4,在前一种情况下声明了自动存储持续时间的对象的生命周期main 将结束,即使在后者中它们不会有。

请注意,这0是强制性的“成功”。如果您愿意,可以使用EXIT_FAILUREand EXIT_SUCCESSfrom <stdlib.h>,但 0 已确定,1 也是如此。另请参阅大于 255 的退出代码 — 可能吗?.

在 C89 中(因此在 Microsoft C 中),没有关于如果main()函数返回但没有指定返回值会发生什么的声明;因此,它会导致未定义的行为。

7.22.4.4exit功能

¶5 最后,控制权返回到主机环境。如果 的值为status0 或,则返回成功终止EXIT_SUCCESS状态的实现定义形式。如果值为 ,则返回状态未成功终止的实现定义形式。否则返回的状态是实现定义的。statusEXIT_FAILURE

标准 C++ — 托管环境

C++11 标准 (ISO/IEC 14882:2011) 说:

3.6.1 主函数[basic.start.main]

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

¶2 实现不应预定义主要功能。该功能不得重载。它应该有一个 int 类型的返回类型,否则它的类型是实现定义的。所有实现都应允许以下两种 main 定义:

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

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

后一种形式argc是从程序运行的环境传递给程序的参数数量。如果argc不为零,则这些参数应作为指向以空结尾的多字节字符串 (NTMBS) (17.5.2.1.4.2) 的初始字符的指针提供,并且argv[0] 应是指向 NTMBS 的初始字符的指针,该名称表示用于调用程序或. 的值应为非负数。的值 应为 0。 [ 注意:建议在 . 之后添加任何其他(可选)参数。——尾注]argv[argc-1]argv[0]""argcargv[argc]argv

¶3 该功能main不得在程序中使用。的链接(3.5)main是实现定义的。[...]

¶5 main 中的 return 语句具有离开 main 函数(销毁具有自动存储持续时间的任何对象)并std::exit以返回值作为参数进行调用的效果。如果控制到达main的末尾没有遇到return语句,效果就是执行

return 0;

C++ 标准明确规定“它 [主函数] 应具有 type 的返回类型int,否则其类型是实现定义的”,并且需要与 C 标准相同的两个签名作为选项支持。因此,C++ 标准直接不允许使用“void main()”,尽管它无法阻止允许替代方案的非标准实现。请注意,C++ 禁止用户调用main(但 C 标准没有)。

C++11 标准中有一段 §18.5开始和结束,与§7.22.4.4exit段落相同中)。EXIT_SUCCESSEXIT_FAILURE<cstdlib>

标准 C——通用扩展

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

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

第三个参数是一个以空结尾的字符串指针列表,每个字符串都是一个环境变量,它有一个名称、一个等号和一个值(可能为空)。如果你不使用这个,你仍然可以通过' extern char **environ;'进入环境。这个全局变量在 POSIX 中是唯一的,因为它没有声明它的标头。

这被 C 标准认可为通用扩展,记录在附件 J 中:

J.5.1 环境参数

¶1 在托管环境中,main 函数接收第三个参数 ,char *envp[]它指向一个以空结尾的指针数组char,每个指针都指向一个字符串,该字符串为程序的执行提供有关环境的信息(5.1. 2.2.1)。

微软 C

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

main 的声明语法是

 int main();

或者,可选地,

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

或者,mainandwmain函数可以声明为返回void(无返回值)。如果您声明mainwmain返回 void,则无法使用 return 语句将退出代码返回给父进程或操作系统。main要在或wmain声明为时返回退出代码void,您必须使用该exit函数。

我不清楚当一个程序退出时会发生什么(什么退出代码返回给父级或操作系统)void main()——而且 MS 网站也保持沉默。

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

Microsoft 页面还列出了其他一些替代方案——wmain()它采用宽字符串等等。

此页面的 Microsoft Visual Studio 2005版本未列为替代版本。Microsoft Visual Studio 2008以后的版本可以。void main()

标准 C — 独立环境

如前所述,上述要求适用于托管环境。如果您使用的是独立环境(这是托管环境的替代方案),那么标准就没有什么可说的了。对于独立环境,不需要调用在程序启动时调用的函数,main并且对其返回类型没有限制。标准说:

5.1.2 执行环境

定义了两种执行环境:独立和托管。在这两种情况下,程序启动都是在执行环境调用指定的 C 函数时发生的。所有具有静态存储持续时间的对象都应在程序启动之前进行初始化(设置为其初始值)。这种初始化的方式和时间是未指定的。程序终止将控制权返回给执行环境。

5.1.2.1 独立环境

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

独立环境中程序终止的效果是实现定义的。

对第 4 条一致性的交叉引用指的是:

¶5严格遵守的程序应仅使用本国际标准中指定的语言和库的那些特性。3)它不应产生依赖于任何未指定、未定义或实现定义的行为的输出,并且不应超过任何最小实现限制。

¶6 两种形式的一致性实现是托管的和独立的。符合要求的托管实现应接受任何严格符合要求的程序。符合标准的独立实现应接受任何严格符合标准的程序,其中库条款(第 7 条)中指定的功能的使用仅限于标准头文件<float.h><iso646.h><limits.h><stdalign.h><stdarg.h><stdbool.h><stddef.h><stdint.h><stdnoreturn.h>. 一个符合要求的实现可能有扩展(包括额外的库函数),只要它们不改变任何严格符合的程序的行为。4)

¶7符合标准的程序是符合标准的实现可接受的程序。5)

3)一个严格符合的程序可以使用条件特性(见 6.10.8.3),只要使用相关宏的适当的条件包含预处理指令保护使用。例如:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4)这意味着一个符合要求的实现除了在本国际标准中明确保留的标识符外,不保留标识符。

5)严格符合的程序旨在最大限度地在符合的实现中移植。符合标准的程序可能取决于符合标准的实现的不可移植特性。

值得注意的是,实际定义任何函数的独立环境所需的唯一标头是<stdarg.h>(甚至那些可能——而且通常是——只是宏)。

标准 C++ — 独立环境

正如 C 标准承认托管和独立环境一样,C++ 标准也是如此。(引自 ISO/IEC 14882:2011。)

1.4 实施合规性 [intro.compliance]

¶7 定义了两种实现:托管实现独立实现。对于托管实现,本国际标准定义了一组可用的库。独立的实现是在没有操作系统的情况下可以执行的实现,并且具有一组实现定义的库,其中包括某些语言支持库 (17.6.1.3)。

¶8 一个符合规范的实现可以有扩展(包括额外的库函数),只要它们不改变任何格式良好的程序的行为。需要实现来诊断使用根据本国际标准格式错误的扩展的程序。然而,这样做之后,他们可以编译和执行这样的程序。

¶9 每个实现都应包括文档,以标识它不支持的所有有条件支持的构造,并定义所有特定于语言环境的特征。3

3)本文档还定义了实现定义的行为;见 1.9。

17.6.1.3 独立实施[合规]

定义了两种实现:托管和独立 (1.4)。对于托管实现,本国际标准描述了一组可用的标头。

一个独立的实现有一组实现定义的头文件。该集合应至少包括表 16 中所示的标题。

提供的标头版本<cstdlib>应至少声明函数abortatexitat_quick_exitexitquick_exit(18.5)。此表中列出的其他标头应满足与托管实现相同的要求。

表 16 — 独立实现的 C++ 头文件

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                       <atomic>

int main()在 C 中使用呢?

C11 标准的标准 §5.1.2.2.1 显示了首选符号 - <code>int main(void) - 但标准中也有两个示例显示int main()§6.5.3.4 ¶8§6.7.6.3 ¶ 20 . 现在,重要的是要注意示例不是“规范的”;它们只是说明性的。如果示例中有错误,它们不会直接影响标准的正文。也就是说,它们强烈地表明了预期的行为,所以如果标准包含int main()在一个例子中,它表明这int main()是不被禁止的,即使它不是首选的符号。

6.5.3.4sizeof_Alignof运算符

…</p>

¶8 示例 3 在此示例中,计算可变长度数组的大小并从函数返回:

#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;
}
于 2013-09-10T14:15:12.000 回答
65

我相信main()应该返回EXIT_SUCCESSor EXIT_FAILURE。它们定义在stdlib.h

于 2008-10-15T12:33:14.733 回答
43

请注意,C 和 C++ 标准定义了两种实现方式:独立式和托管式。

  • C90 托管环境

允许的形式1

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

main (void)
main (int argc, char *argv[])
/*... etc, similar forms with implicit int */

评论:

前两个被明确声明为允许的形式,其他的被隐式允许,因为 C90 允许“隐式 int”作为返回类型和函数参数。不允许使用其他形式。

  • C90 独立环境

允许使用任何形式或名称的 main 2

  • C99 托管环境

允许的表格3

int 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 独立式环境

允许使用任何形式或名称的 main 6

  • C11 托管环境

允许的表格7

int main (void)
int main (int argc, char *argv[])
/* or in some other implementation-defined manner. */
  • C11 独立式环境

允许使用任何形式或名称的 main 8


请注意,int main()在上述任何版本中,它从未被列为任何托管 C 实现的有效形式。在 C 中,不同于 C++,()并且(void)有不同的含义。前者是一个过时的功能,可能会从语言中删除。请参阅 C11 未来语言方向:

6.11.6 函数声明器

使用带空括号的函数声明符(不是原型格式参数类型声明符)是一个过时的特性。


  • C++03 托管环境

允许的表格9

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

评论:

请注意第一种形式中的空括号。在这种情况下,C++ 和 C 是不同的,因为在 C++ 中,这意味着函数不接受参数。但在 C 中,这意味着它可以采用任何参数。

  • C++03 独立环境

启动时调用的函数的名称是实现定义的。如果它被命名main(),它必须遵循规定的表格10

// implementation-defined name, or 
int main ()
int main (int argc, char *argv[])
  • C++11 托管环境

允许的表格11 :

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

评论:

标准的文本已更改,但含义相同。

  • C++11 独立环境

启动时调用的函数的名称是实现定义的。如果它被命名main(),它必须遵循规定的表格12

// implementation-defined name, or 
int main ()
int main (int argc, char *argv[])

参考

  1. ANSI X3.159-1989 2.1.2.2 托管环境。“程序启动”

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

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

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

int main(int argc, char *argv[]) { /* ... */ }
  1. ANSI X3.159-1989 2.1.2.1 独立环境:

在独立环境中(C 程序的执行可能在没有操作系统的任何好处的情况下发生),程序启动时调用的函数的名称和类型是实现定义的。

  1. ISO 9899:1999 5.1.2.2 托管环境 -> 5.1.2.2.1 程序启动

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

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

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

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

或等价物;9) 或以其他一些实现定义的方式。

  1. 国际标准的基本原理 — 编程语言 — C,修订版 5.10。5.1.2.2 托管环境 --> 5.1.2.2.1 程序启动

main 参数的行为,以及 exit、main 和 atexit(参见第 7.20.4.2 节)的交互行为已被编纂,以遏制 argv 字符串的表示形式以及 main 返回值的含义中的一些不必要的变化。

将 argc 和 argv 作为 main 的参数的规范认可了广泛的先前实践。argv[argc] 需要为空指针,以提供对列表末尾的冗余检查,也是基于惯例。

main 是唯一可以用零个或两个参数可移植地声明的函数。(其他函数的参数数量必须在调用和定义之间完全匹配。)这种特殊情况只是认识到当程序不访问程序参数字符串时将参数留给 main 的普遍做法。虽然许多实现支持两个以上的 main 参数,但标准既不祝福也不禁止这种做法;用三个参数定义 main 的程序并不严格符合(参见 §J.5.1.)。

  1. ISO 9899:1999 5.1.2.2 托管环境 --> 5.1.2.2.3 程序终止

如果 main 函数的返回类型是与 int 兼容的类型,则从初始调用到 main 函数的 return 等效于以 main 函数返回的值作为参数调用 exit 函数;11)到达}终止的main 函数返回值 0。如果返回类型与 int 不兼容,则返回给宿主环境的终止状态是未指定的。

  1. ISO 9899:1999 5.1.2.1 独立环境

在独立环境中(C 程序的执行可能在没有操作系统的任何好处的情况下发生),程序启动时调用的函数的名称和类型是实现定义的。

  1. ISO 9899:2011 5.1.2.2 托管环境 -> 5.1.2.2.1 程序启动

本节与上面引用的 C99 相同。

  1. ISO 9899:1999 5.1.2.1 独立环境

本节与上面引用的 C99 相同。

  1. ISO 14882:2003 3.6.1 主要功能

实现不应预定义主要功能。该功能不得重载。它应该有一个 int 类型的返回类型,否则它的类型是实现定义的。所有实现都应允许以下两种 main 定义:

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

int main(int argc, char* argv[]) { /* ... */ }
  1. ISO 14882:2003 3.6.1 主要功能

独立环境中的程序是否需要定义主要功能是实现定义的。

  1. ISO 14882:2011 3.6.1 主要功能

实现不应预定义主要功能。该功能不得重载。它应该有一个 int 类型的返回类型,否则它的类型是实现定义的。所有实现都应允许

— () 的函数返回 int 和

— (int, pointer to pointer to char) 返回 int 的函数

作为 main 的类型(8.3.5)。

  1. ISO 14882:2011 3.6.1 主要功能

本节与上面引用的 C++03 相同。

于 2015-07-07T08:07:30.277 回答
30

成功返回 0,错误返回非零。这是 UNIX 和 DOS 脚本用于找出程序发生了什么的标准。

于 2008-10-15T12:16:51.503 回答
8

main()在 C89 和 K&R C 中,未指定的返回类型默认为“int”。

return 1? return 0?
  1. 如果不写return语句int main(),则关闭}默认返回0。

(仅在 c++ 和 c99 以后,对于 c90 必须编写 return 语句。请参阅为什么 main 此处不返回 0?

  1. return 0return 1将被父进程接收。在 shell 中,它进入一个 shell 变量,如果您从 shell 运行程序而不使用该变量,那么您不必担心main().

请参阅如何获取我的 main 函数返回的内容?.

$ ./a.out
$ echo $?

这样你可以看到它是$?接收返回值的最低有效字节的变量main()

在 Unix 和 DOS 脚本中,return 0通常返回成功和非零错误。这是 Unix 和 DOS 脚本用来找出程序发生了什么并控制整个流程的标准。

于 2011-12-27T08:02:51.533 回答
7

请记住,即使您返回一个 int,某些操作系统 (Windows) 也会将返回的值截断为单个字节 (0-255)。

于 2008-10-15T15:22:13.313 回答
4

操作系统可以使用返回值来检查程序是如何关闭的。

返回值 0 在大多数操作系统中通常意味着 OK(无论如何我都能想到的那些)。

当你自己调用一个进程时也可以检查它,看看程序是否退出并正确完成。

不仅仅是一个编程约定。

于 2011-07-01T16:32:34.087 回答
3

的返回值main()显示程序如何退出。如果返回值是zero,则表示执行成功,而任何非零值都表示执行中出现问题。

于 2011-07-01T23:30:59.867 回答
2

返回 0 应该告诉程序员程序已成功完成工作。

于 2012-11-23T07:29:29.500 回答
2

忽略return 0

当 C 或 C++ 程序到达末尾时main,编译器会自动生成返回 0 的代码,因此无需return 0;在末尾显式放置main.

注意:当我提出这个建议时,几乎总是跟着两种评论之一:“我不知道。” 或“这是个坏建议!” 我的理由是,依赖标准明确支持的编译器行为是安全且有用的。对于 C,从 C99 开始;参见 ISO/IEC 9899:1999 第 5.1.2.2.3 节:

[...] 从对函数的初始调用返回main等效于以exit函数返回的值main作为参数调用函数;到达}终止main函数的返回值 0。

对于 C++,从 1998 年的第一个标准开始;参见 ISO/IEC 14882:1998 第 3.6.1 节:

如果控制到达main末尾没有遇到return语句,效果就是执行return 0;

从那时起,这两个标准的所有版本(C99 和 C++98)都保持了相同的想法。我们依赖于 C++ 中自动生成的成员函数,很少有人在函数return;末尾写明确的语句void。反对省略的原因似乎可以归结为“看起来很奇怪”。如果您像我一样对更改 C 标准的理由感到好奇,请阅读此问题。另请注意,在 1990 年代初期,这被认为是“草率的做法”,因为当时它是未定义的行为(尽管得到广泛支持)。

此外,C++ 核心指南包含多个return 0;在末尾省略的main实例,并且没有写入显式返回的实例。尽管该文件中还没有关于这个特定主题的具体指导方针,但这似乎至少是对这种做法的默许。

所以我主张省略它;其他人不同意(通常非常激烈!)在任何情况下,如果您遇到省略它的代码,您就会知道标准明确支持它并且您会知道它的含义。

于 2017-04-22T11:34:54.647 回答
1

如果您确实存在与从进程返回整数的效率相关的问题,您可能应该避免多次调用该进程以致该返回值成为问题。

如果你这样做(多次调用一个进程),你应该找到一种方法将你的逻辑直接放在调用者中,或者放在一个 DLL 文件中,而不为每次调用分配一个特定的进程;在这种情况下,多进程分配给您带来了相关的效率问题。

详细地说,如果您只想知道返回 0 是否比返回 1 效率更高或更低,在某些情况下它可能取决于编译器,但一般来说,假设它们是从相同的源(本地、字段、常量、嵌入式在代码、函数结果等中)它需要完全相同数量的时钟周期。

于 2011-03-03T11:56:57.407 回答
1

返回的内容取决于您要对可执行文件执行的操作。例如,如果您将程序与命令行 shell 一起使用,那么您需要返回 0 表示成功,返回非 0 表示失败。然后,您将能够根据代码的结果在带有条件处理的 shell 中使用该程序。您也可以根据您的解释分配任何非零值,例如对于严重错误,不同的程序退出点可以终止具有不同退出值的程序,并且调用 shell 可以通过检查返回的值来决定做什么。如果代码不打算与 shell 一起使用并且返回的值不会打扰任何人,那么它可能会被省略。我个人使用签名int main (void) { .. return 0; .. }

于 2011-03-10T14:11:33.747 回答
1

这是返回码用法的一个小演示......

当使用 Linux 终端提供的各种工具时,可以使用返回码,例如在进程完成后进行错误处理。假设存在以下文本文件 myfile:

这是一些示例,用于检查 grep 的工作原理。

当您执行 grep 命令时,会创建一个进程。一旦它通过(并且没有中断),它会返回一些介于 0 和 255 之间的代码。例如:

$ grep order myfile

如果你这样做

$ echo $?
$ 0

你会得到一个0。为什么?因为grep找到匹配项并返回退出代码 0,这是成功退出的常用值。让我们再次检查一下,但有些内容不在我们的文本文件中,因此找不到匹配项:

$ grep foo myfile
$ echo $?
$ 1

由于 grep 未能将令牌“foo”与我们文件的内容匹配,因此返回码为 1(这是发生故障时的常见情况,但如上所述,您有很多值可供选择)。

现在下面的 bash 脚本(只需在 Linux 终端中键入)虽然非常基本,但应该给出一些错误处理的想法:

$ 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() 的返回值)。

于 2015-02-10T22:22:08.667 回答
1

在 C 和 C++ 中定义 main() 函数的正确(最有效)方法是什么——int main() 或 void main()——为什么?

那些词“(最有效)”并没有改变问题。除非您处于独立环境中,否则有一种普遍正确的声明方式main(),那就是返回 int。

main()在 C 和 C++ 中应该返回什么?

这不是应该返回 main()的,而是应该返回的。 当然,是别人调用的函数。您无法控制调用. 因此,您必须使用类型正确的签名声明以匹配其调用者。你在这件事上根本没有任何选择。您不必问自己什么效率更高或更低,或者风格更好或更差,或类似的事情,因为答案已经由 C 和 C+ 标准完美定义。只要跟着他们。 main()main()main()main()

如果 int main() 那么返回 1 还是返回 0?

0 表示成功,非零表示失败。同样,不是您需要(或获得)选择的东西:它是由您应该遵守的接口定义的。

于 2017-10-03T21:56:28.587 回答
0

在 C 中,C11 标准的第 5.1.2.2.1 节(强调我的):

它应定义为返回类型int且不带参数:

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

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

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

但是对于像我这样的初学者来说,一个抽象的例子可以让我掌握它:

当您在程序中编写一个方法时,例如int read_file(char filename[LEN]);,作为该方法的调用者,您希望知道一切是否顺利(因为可能会发生故障,例如找不到文件)。通过检查方法的返回值,您可以知道一切是否顺利,这是该方法向您发出成功执行(或不成功)信号的一种机制,并让调用者(您,例如在您的 main 方法中)决定如何处理意外故障。

所以现在想象我为一个用于更复杂系统的微机制编写了一个 C 程序。当系统调用微机制时,它想知道一切是否按预期进行,以便它可以处理任何潜在的错误。如果 C 程序的 main 方法会返回 void,那么调用系统如何知道其子系统(微机制)的执行情况?它不能,这就是 main() 返回 int 的原因,以便与调用者通信成功(或不成功)执行。

换句话说:

合理的是主机环境(即操作系统(OS))需要知道程序是否正确完成。如果没有 int 兼容类型作为返回类型(例如 void),“返回到主机环境的状态是未指定的”(即大多数操作系统上的未定义行为)。

于 2020-10-10T15:34:27.617 回答
-2

在 Windows 上,如果程序由于访问冲突而崩溃,退出代码将为STATUS_ACCESS_VIOLATION (0xC0000005). 对于来自 x86 异常的其他类型的崩溃也类似。

因此,除了您返回main或传递给的内容之外,还有一些事情exit可能会导致看到退出代码。

于 2021-08-29T18:52:49.247 回答