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

什么是在C和C ++中定义main()函数的正确(最有效的)方法 – int main()void main() – 为什么? 如果int main()然后return 1return 0


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

  • C的main()函数的有效签名是什么?
  • main()函数的返回types
  • void main()int main()之间的区别?
  • main()在C ++中的签名
  • 什么是main()的正确声明? – 对于C ++来说,确实有非常好的答案。
  • C中main()函数的样式
  • 在C中返回main()方法的types
  • int main() vs void main() in C

有关:

  • int main(int argc, char **argv)int main(int argc, char **argv)
  • int main(int argc, char *argv[])
  • char *envp[]作为main()可移植性的第三个参数吗?
  • int main()函数是否必须在所有编译器中返回一个值?
  • 为什么C和C ++中的main()函数的types留给用户定义?
  • 为什么int main(){}编译?
  • main()在C ++ 14中的法律定义?

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

 int main() 

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

相当于

 int main(int argc, char** argv) 

值得注意的是,在C ++中, int main()可以不带返回值,在这一点上它默认返回0.对于C99程序也是如此。 是否应该省略返回0是否可以辩论。 有效的C程序主签名的范围要大得多。

而且,效率不是mainfunction的问题。 它只能按照C ++标准进入和留下一次(标记程序开始和终止)。 对于C,情况是不同的,重新进入main()是允许的,但应该可以避免。

被接受的答案似乎是针对C ++的,所以我想我会添加一个与C有关的答案,这在几个方面有所不同。

ISO / IEC 9899:1989(C90):

main()应该声明为:

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

或同等学历。 例如, int main(int argc, char *argv[])等价于第二个。 此外,因为它是默认的,所以可以省略int返回types。

如果一个实现允许的话, main()可以用其他方式声明,但是这会使程序实现定义,不再严格符合。

标准定义了3个严格符合(即不依赖于实现定义的行为)的返回值: 0EXIT_SUCCESS用于成功终止, EXIT_FAILURE用于不成功的终止。 其他任何值都是非标准的,并且定义了实现。 main()在最后必须有一个显式的return语句来避免未定义的行为。

最后,从标准的angular度来看,从程序中调用main()是没有问题的。

ISO / IEC 9899:1999(C99):

对于C99,除了以下情况外,其它内容与上述相同:

  • int返回types不能省略。
  • 你可以省略main()的return语句。 如果你这样做,并且main()完成,那么隐式return 0

标准C – 托pipe环境

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

5.1.2.2.1程序启动

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

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

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

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

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

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

  • 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应该可以被程序修改,并在程序启动和程序终止之间保留它们的最后存储的值。

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

程序终止在C99或C11中

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

5.1.2.2.3程序终止

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

11)根据6.2.4,在main声明的具有自动存储时间的物体的寿命将在前一种情况下结束,即使在后者中不存在的情况下。

请注意, 0被强制为“成功”。 如果您愿意,您可以使用<stdlib.h> EXIT_FAILUREEXIT_SUCCESS ,但是0已经build立好了,所以也是1.另请参阅退出代码大于255 – 可能吗? 。

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

7.22.4.4 exitfunction

¶5最后,控制权返回到主机环境。 如果status值为零或EXIT_SUCCESS ,则返回状态成功终止的实现定义forms。 如果status值为EXIT_FAILURE ,则返回状态不成功终止的实现定义forms。 否则,返回的状态是实现定义的。

标准C ++ – 托pipe环境

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

3.6.1主要function[basic.start.main]

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

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

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

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

在后一种forms中, argc应该是程序运行环境中传递给程序的参数的数量。 如果argc不为零,那么这些参数应该在argv[0]argv[argc-1]作为指向NULL结尾多字节string(NTMBS)(17.5.2.1.4.2)和argv[0]的初始字符的指针提供指向表示用于调用程序的名称的NTMBS的初始字符的指针或""argc的值应该是非负的。 argv[argc]的值应为0. [注意:build议在argv之后再添加(可选)参数。 – 注意]

¶3函数main不能在程序中使用。 main的连接(3.5)是实现定义的。 […]

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

 return 0; 

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

在C ++ 11标准中有一段§18.5的开始和终止 ,与§7.22.4.4中的段落相同。C11标准中exit函数 (上面引用的),除了一个脚注外(它只是logging了EXIT_SUCCESSEXIT_FAILURE<cstdlib>中定义)。

标准C – 公共扩展

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

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

第三个参数是一个以空字符结尾的string指针列表,每个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()的程序确实退出时,我不清楚发生了什么(退出代码返回到父代或OS),而且MS网站也是无声的。

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

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

此页面的Microsoft Visual Studio 2005版本不会列出void main()作为替代方法。 Microsoft Visual Studio 2008以后的版本可以。

标准C – 独立环境

如前所述,上述要求适用于托pipe环境。 如果您正在使用独立环境(这是托pipe环境的替代scheme),那么标准就不那么重要了。 对于一个独立的环境来说,在程序启动时调用的函数不需要被调用为main函数,并且它的返回types没有限制。 标准说:

5.1.2执行环境

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

5.1.2.1独立环境

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

程序终止在独立环境中的影响是由实现定义的。

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

¶5 严格符合的程序只能使用本标准规定的语言和库的特征。 3)根据任何未指定的,未定义的或实现定义的行为,不得产生输出,并且不得超过任何最小实现限制。

¶6两种forms的一致性实施是托pipe独立的合规的托pipe实施应接受任何严格符合的程序。 符合独立实现应接受任何严格符合程序,其中使用库条款(第7条)中指定的function限制在标准头文件<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),前提是使用相关macros指令的适当条件包含预处理指令保护使用。 例如:

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

4)这意味着符合的实现不保留本标准中明确保留的标识符。

5)严格符合的程序旨在最大限度地兼容执行。 符合的程序可能取决于符合实现的非便携特征。

值得注意的是,实际上定义了任何函数的独立环境所需的唯一头文件是<stdarg.h> (甚至这些头文件也可能是,而且通常只是macros)。

标准C ++ – 独立环境

正如C标准认识到托pipe和独立环境一样,C ++标准也是如此。 (来自ISO / IEC 14882:2011的引文。)

1.4执行合规性[intro.compliance]

¶7定义了两种实现: 托pipe实现独立实现 。 对于托pipe实现,这个国际标准定义了一组可用的库。 独立实现可以在没有操作系统好处的情况下执行,并且有一个实现定义的库集合,包含某些语言支持库(17.6.1.3)。

¶8一致性实现可以有扩展(包括附加的库函数),只要它们不改变任何格式良好的程序的行为。 根据本国际标准,需要实施诊断使用不合格的扩展程序。 但是,这样做,他们可以编译和执行这样的程序。

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

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

17.6.1.3独立实施[compliance]

定义了两种实现:托pipe和独立(1.4)。 对于托pipe实现,本国际标准描述了可用标题集。

独立实现有一个实现定义的标题集。 该组至less应包括表16所示的标题。

头文件<cstdlib>的提供版本至less要声明函数abortatexitat_quick_exitexitquick_exit (18.5)。 本表中列出的其他标题应符合与托pipe实施相同的要求。

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

怎么在C中使用int main()

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

6.5.3.4 sizeof_Alignof运算符

¶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; } 

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

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

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

  • C90托pipe的环境

    允许的forms1

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

    注释:

    前两者明确表示为允许的forms,其他则是隐式允许的,因为C90允许“隐式int”用于返回types和函数参数。 没有其他forms是允许的。

  • C90独立式的环境

    任何forms或名称的主要是允许的2

  • C99托pipe的环境

    允许的forms3

     int main (void) int main (int argc, char *argv[]) /* or in some other implementation-defined manner. */ 

    注释:

    C99删除了“隐式int”,所以main()不再有效。

    引入了一个奇怪的,含糊不清的句子或“其他一些实现定义的方式”。 这可以被解释为“ int main()的参数可能不同”或者“main可以有任何实现定义的forms”。

    有些编纂者select以后一种方式来解释这个标准。 可以说,由于它是模棱两可的,所以不能简单地表明它们本身并不严格符合标准。

    然而,允许完全疯狂的forms主要()可能(?)不是这个新的句子的意图。 C99的基本原理(不是规范的)意味着这个句子引用了int main 4个参数。

    然而,主持环境项目终止部分继续争论主要不返回整数5的情况 。 虽然这一部分不是主要应该如何声明的规范,但这绝对意味着即使在托pipe系统上,主体也可以以完全实现的方式来声明。

  • C99独立式的环境

    任何forms或名称的主要是允许的6

  • C11托pipe的环境

    允许的forms7

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

    任何forms或名称的主要是允许的8


请注意, int main()从来没有被列为任何上述版本中任何托pipe实现C的有效表单。 在C中,与C ++不同, ()(void)有不同的含义。 前者是可以从语言中删除的过时特征。 请参阅C11未来的语言指导:

6.11.6函数声明符

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


  • C ++ 03托pipe环境

    允许的forms9

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

    注释:

    请注意第一种forms的空括号。 C ++和C在这种情况下是不同的,因为在C ++中这意味着该函数不带参数。 但是在C中,这意味着它可能需要任何参数。

  • C ++ 03独立环境

    在启动时调用的函数的名称是实现定义的。 如果它被命名为main(),它必须遵循所述的forms10

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

    允许的forms11

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

    注释:

    标准的文字已被改变,但意思相同。

  • C ++ 11独立环境

    在启动时调用的函数的名称是实现定义的。 如果它被命名为main(),它必须遵循所述的forms12

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

参考

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

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

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

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

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

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

  3. ISO 9899:1999 5.1.2.2托pipe环境 – > 5.1.2.2.1程序启动

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

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

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

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

    或等同物; 9)或以某种其他实施方式定义的方式。

  4. 国际标准的基本原理 – 编程语言 – C,修订5.10。 5.1.2.2托pipe环境 – > 5.1.2.2.1程序启动

    主要参数以及exit,main和atexit(参见§720.4.2)的相互作用的行为已被编纂为遏制argvstring表示forms中的一些不需要的变体,以及由main返回的值的含义。

    argc和argv作为主要参数的规范认可了大量的先前的实践。 argv [argc]必须是一个空指针,以便在列表的末尾提供冗余检查,同样也是基于惯例。

    main是唯一可以用0或2个参数声明的函数。 (其他函数参数的数量必须与调用和定义完全一致)。这种特殊情况只是简单地认识到,当程序不访问程序参数string时,将参数从主参数中删除的普遍做法。 虽然许多实现支持主要的两个以上的参数,但是这样的实践既不被标准祝福也不被禁止; 用三个参数来定义主体的程序并不严格符合(见§5.5.1)。

  5. ISO 9899:1999 5.1.2.2托pipe环境 – > 5.1.2.2.3程序终止

    如果主函数的返回types是与int兼容的types,则从初始调用返回到主函数相当于使用主函数返回的值作为参数来调用exit函数; 11)达到终止主函数返回值0.如果返回types与int不兼容,则返回到主机环境的终止状态是未指定的。

  6. ISO 9899:1999 5.1.2.1独立环境

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

  7. ISO 9899:2011 5.1.2.2托pipe环境 – > 5.1.2.2.1程序启动

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

  8. ISO 9899:1999 5.1.2.1独立环境

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

  9. ISO 14882:2003 3.6.1主要function

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

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

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

    是否需要在独立环境中的程序来定义主要function是实施定义的。

  11. ISO 14882:2011 3.6.1主要function

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

    – ()返回int和的函数

    – (int,指向char的指针)返回int的函数

    作为主要的types(8.3.5)。

  12. ISO 14882:2011 3.6.1主要function

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

Keep in mind that,even though you're returning an int, some OSes (Windows) truncate the returned value to a single byte (0-255).

main() in C89 and K&R C unspecified return types default to int

 return 1? return 0? 
  1. If you do not write a return statement in int main() then the closing { will return 0 by default

  2. Return 0 or return 1 will be received by the environment variable of the OS. So if you are not using that environment variable then you should not worry about the return value of main() .

See How can I get what my main function has returned?

 $ ./a.out $ echo $? 

This way you can see that it is the environment variable $? which receives the last one byte of return value of main() .

So if you are writing any script then you should take care of the return value of main() , otherwise don't.

In Unix and DOS scripting, return 0 on success and non-zero for error are usually returned. This is the standard used by Unix and DOS scripting to find out what happened with your program and controlling the whole flow.

The return value can be used by the operating system to check how the program was closed.

Return value 0 usually means OK in most operating systems (the ones I can think of anyway).

It also can be checked when you call a process yourself, and see if the program exited and finished properly.

It's NOT just a programming convention.

I was under the impression that standard specifies that main doesn't need a return value as a successful return was OS based (zero in one could be either a success or a failure in another), therefore the absence of return was a cue for the compiler to insert the successful return itself.

However I usually return 0.

What to return depends on what you want to do with the executable. For example if you are using your program with a command line shell, then you need to return 0 for a success and a non zero for failure. Then you would be able to use the program in shells with conditional processing depending on the outcome of your code. Also you can assign any nonzero value as per your interpretation, for example for critical errors different program exit points could terminate a program with different exit values , and which is available to the calling shell which can decide what to do by inspecting the value returned. If the code is not intended for use with shells and the returned value does not bother anybody then it might be omitted. I personally use the signature int main (void) { .. return 0; .. }

If you really have issues related to efficiency of returning an integer from a process, you should probably avoid to call that process so many times that this return value becomes an issue.

If you are doing this (call a process so many times), you should find a way to put your logic directly inside the caller, or in a DLL file, without allocate a specific process for each call; the multiple process allocations bring you the relevant efficiency problem in this case.

In detail, if you only want to know if returning 0 is more or less efficient than returning 1, it could depend from the compiler in some cases, but generically, assuming they are read from the same source (local, field, constant, embedded in the code, function result, etc.) it requires exactly the same number of clock cycles.

The return value of main() shows how the program exited. If the return value is zero it means that the execution was successful while any non-zero value will represent that something went bad in the execution.

Returning 0 should tell the programmer that the program has successfully finished the job.

This basically depends on your execution environment (the OS). C implies that it will be run by a UNIX like OS which expects the program to return a (small? 1 Byte? can't remember) integer to indicate success / failure.

You should probably just use int main(int argc, char** argv) .

Here is a small demonstration of the usage of return codes…

When using the various tools that the Linux terminal provides one can use the return code for example for error handling after the process has been completed. Imagine that the following text file myfile is present:

This is some example in order to check how grep works.

When you execute the grep command a process is created. Once it is through (and didn't break) it returns some code between 0 and 255. For example:

 $ grep order myfile 

如果你这样做

 $ echo $? $ 0 

you will get a 0. Why? Because grep found a match and returned an exit code 0, which is the usual value for exiting with a success. Let's check it out again but with something that is not inside our text file and thus no match will be found:

 $ grep foo myfile $ echo $? $ 1 

Since grep failed to match the token "foo" with the content of our file the return code is 1 (this is the usual case when a failure occurs but as stated above you have plenty of values to choose from).

Now the following bash script (simply type it in a Linux terminal) although very basic should give some idea of error handling:

 $ grep foo myfile $ CHECK=$? $ [ $CHECK -eq 0] && echo 'Match found' $ [ $CHECK -ne 0] && echo 'No match was found' $ No match was found 

After the second line nothing is printed to the terminal since "foo" made grep return 1 and we check if the return code of grep was equal to 0. The second conditional statement echoes its message in the last line since it is true due to CHECK == 1.

As you can see if you are calling this and that process it is sometimes essential to see what it has returned (by the return value of main()).

Omit return 0

When a C or C++ program reaches the end of main the compiler will automatically generate code to return 0, so there is no need to put return 0; explicitly at the end of main .

Note: when I make this suggestion, it's almost invariably followed by one of two kinds of comments: "I didn't know that." or "That's bad advice!" My rationale is that it's safe and useful to rely on compiler behavior explicitly supported by the standard. For C, since C99; see ISO/IEC 9899:1999 section 5.1.2.2.3:

[…] 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; reaching the } that terminates the main function returns a value of 0.

For C++, since the first standard in 1998; see ISO/IEC 14882:1998 section 3.6.1:

If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;

All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return; statements at the end of a void function. Reasons against omitting seem to boil down to "it looks weird" . If, like me, you're curious about the rationale for the change to the C standard read this question . Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.

So I advocate omitting it; others disagree (often vehemently!) In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.

What is the correct (most efficient) way to define the main() function in C and C++ — int main() or void main() — and why?

Those words "(most efficient)" don't change the question. Unless you're in a freestanding environment, there is one universally correct way to declare main() , and that's as returning int.

What should main() return in C and C++?

It's not what should main() return, it's what does main() return. main() is, of course, a function that someone else calls. You don't have any control over the code that calls main() . Therefore, you must declare main() with a type-correct signature to match its caller. You simply don't have any choice in the matter. You don't have to ask yourself what's more or less efficient, or what's better or worse style, or anything like that, because the answer is already perfectly well defined, for you, by the C and C+ standards. Just follow them.

If int main() then return 1 or return 0?

0 for success, nonzero for failure. Again, not something you need to (or get to) pick: it's defined by the interface you're supposed to be conforming to.

void main() is forbidden after C90. main should return a value. I used to return 0.