协慌网

登录 贡献 社区

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

答案

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

int main()

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

相当于

int main(int argc, char** argv)

还值得注意的是,在 C ++ 中, int main()保留为没有返回语句,此时它默认为返回 0。C99 程序也是如此。是否return 0;是否应省略还是值得商 debate。有效的 C 程序主签名的范围要大得多。

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

可接受的答案似乎是针对 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[]) ),但这使程序实现得以定义,并且不再严格符合。

该标准定义了三个严格符合要求的返回值(即,不依赖于实现定义的行为): 0EXIT_SUCCESS表示成功终止, EXIT_FAILURE表示终止失败。任何其他值都是非标准的,并且定义为实现。在 C90 中, main()必须在末尾具有显式的return语句,以避免未定义的行为。在 C99 及更高版本中,您可以省略main()的 return 语句。如果这样做,并且main()完成,则隐式return 0

最后,从标准的角度来看,从 C 程序递归main()

标准 C —托管环境

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

5.1.2.2.1 程序启动

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

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

或带有两个参数( argcargv ,因为它们是声明它们的函数的局部名称):

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

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

如果声明了它们,则主函数的参数应服从以下约束:

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

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

C99 或 C11 中的程序终止

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

5.1.2.2.3 程序终止

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

11) main声明的具有自动存储期限的对象的生存期将在前一种情况下终止,即使在后者没有的情况下也是如此。

请注意,将0强制为 “成功”。如果愿意,可以使用<stdlib.h> EXIT_FAILUREEXIT_SUCCESS ,但是 0 已很好建立,1 也是如此。另请参见大于 255 的退出代码 - 可能吗?

在 C89(因此在 Microsoft C 中)中,没有关于main()函数返回但未指定返回值的情况的声明;因此,它导致不确定的行为。

7.22.4.4 exit功能

¶5 最后,控制权返回到主机环境。 status的值为零或EXIT_SUCCESS ,则返回实现定义的状态成功终止的形式。如果status值为EXIT_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为非零,则这些参数必须通过argv[argc-1] argv[0]提供,作为指向以空字符结尾的多字节字符串(NTMBS)(17.5.2.1.4.2)的初始字符的指针,而argv[0]为指向 NTMBS 初始字符的指针,代表用于调用程序的名称或""argc的值应为非负数。 argv[argc]的值应为 0。[注意:建议在argv之后添加任何其他(可选)参数。 —尾注]

¶3 函数main不得在程序内使用。 main的链接(3.5)是实现定义的。 [...]

¶5main 中的 return 语句的作用是保留 main 函数(销毁具有自动存储持续时间的所有对象)并以返回值作为参数std::exit如果控制在没有遇到 return 语句的情况下到达了 main 的末尾,则其结果是执行

return 0;

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

有 §18.5开始的在 C ++ 11 标准段落和终止是与从 §7.22.4.4 段落exit在 C11 标准函数(上面引述的),除了一个脚注(其简单地文档EXIT_SUCCESSEXIT_FAILURE <cstdlib>中定义)。

标准 C —通用扩展

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

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

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

这是 C 标准公认的通用扩展,记录在附件 J 中:

J.5.1 环境参数

¶1 在托管环境中,主函数接收第三个参数char *envp[] 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()的程序确实退出时会发生什么(退出代码返回给父级或 OS)- 并且 MS 网站也处于静默状态。

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

Microsoft 页面还列出了其他一些替代方法— wmain()需要宽字符串,还有其他一些替代方法。

此页的 Microsoft Visual Studio 2005版本没有列出void main()作为替代方案。从 Microsoft Visual Studio 2008起的版本都可以使用。

标准 C - 独立环境

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

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.

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.

The effect of program termination in a freestanding environment is implementation-defined.

The cross-reference to clause 4 Conformance refers to this:

¶5 A strictly conforming program shall use only those features of the language and library specified in this International Standard.3) It shall not produce output dependent on any unspecified, undefined, or implementation-defined behavior, and shall not exceed any minimum implementation limit.

¶6 The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>. A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program.4)

¶7 A conforming program is one that is acceptable to a conforming implementation.5)

3) A strictly conforming program can use conditional features (see 6.10.8.3) provided the use is guarded by an appropriate conditional inclusion preprocessing directive using the related macro. For example:

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

4) This implies that a conforming implementation reserves no identifiers other than those explicitly reserved in this International Standard.

5) Strictly conforming programs are intended to be maximally portable among conforming implementations. Conforming programs may depend upon non-portable features of a conforming implementation.

It is noticeable that the only header required of a freestanding environment that actually defines any functions is <stdarg.h> (and even those may be — and often are — just macros).

Standard C++ — Freestanding Environment

Just as the C standard recognizes both hosted and freestanding environment, so too does the C++ standard. (Quotes from ISO/IEC 14882:2011.)

1.4 Implementation compliance [intro.compliance]

¶7 Two kinds of implementations are defined: a hosted implementation and a freestanding implementation. For a hosted implementation, this International Standard defines the set of available libraries. A freestanding implementation is one in which execution may take place without the benefit of an operating system, and has an implementation-defined set of libraries that includes certain language-support libraries (17.6.1.3).

¶8 A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

¶9 Each implementation shall include documentation that identifies all conditionally-supported constructs that it does not support and defines all locale-specific characteristics.3

3) This documentation also defines implementation-defined behavior; see 1.9.

17.6.1.3 Freestanding implementations [compliance]

Two kinds of implementations are defined: hosted and freestanding (1.4). For a hosted implementation, this International Standard describes the set of available headers.

A freestanding implementation has an implementation-defined set of headers. This set shall include at least the headers shown in Table 16.

The supplied version of the header <cstdlib> shall declare at least the functions abort, atexit, at_quick_exit, exit, and quick_exit (18.5). The other headers listed in this table shall meet the same requirements as for a hosted implementation.

Table 16 — C++ headers for freestanding implementations

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>

What about using int main() in C?

The standard §5.1.2.2.1 of the C11 standard shows the preferred notation — int main(void) — but there are also two examples in the standard which show int main(): §6.5.3.4 ¶8 and §6.7.6.3 ¶20. Now, it is important to note that examples are not 'normative'; they are only illustrative. If there are bugs in the examples, they do not directly affect the main text of the standard. That said, they are strongly indicative of expected behaviour, so if the standard includes int main() in an example, it suggests that int main() is not forbidden, even if it is not the preferred notation.

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