【问题标题】:Why is the type of the main function in C and c++ left to the user to define? [duplicate]为什么 C 和 C++ 中的 main 函数的类型留给用户定义? [复制]
【发布时间】:2011-07-14 20:20:39
【问题描述】:

为什么main() 是用户定义的函数?

我什么时候使用void main()int main()

【问题讨论】:

  • every 非库函数的类型留给用户定义。 main 的不同之处在于选择范围更窄。

标签: c++ c main


【解决方案1】:

编辑这个答案并不完整,因为它并没有真正解决奇怪的句子“或以某种实现定义的方式”。我现在写了一个more complete answer,它还涉及 C90、C11 和 C++。 编辑结束

以下是 C 标准 (ISO C 9899:1999):

5.1.2.1 独立环境

在独立的环境中(在 哪个C 程序执行可能发生 没有任何操作的好处 系统),名称和类型 程序启动时调用的函数是 实现定义。 / .. / 效果 在一个程序终止 独立的环境是 实现定义。

5.1.2.2 托管环境

无需提供托管环境,但 应符合以下 规格(如果有)。

5.1.2.2.1 程序启动

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

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

或带两个参数(指 这里是 argc 和 argv,尽管有 可以使用名称,因为它们是本地的 到它们所在的功能 声明):

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

C++ 标准中的文本或多或少是相同的。 注意,文本中的“程序启动”是托管环境的子条款

这意味着:

  • 如果您的程序在无主机环境中运行(您的程序是嵌入式系统或操作系统),它可能有任何返回类型。 void main() 是最常见的。

  • 如果您的程序在托管环境中运行(在操作系统之上),main() 必须返回 int,并且可能有其他参数。

【讨论】:

  • +1,获取有效答案。但也许还有更多的解释。在独立环境中,main 的返回类型是实现定义:这并不意味着由程序员来决定,而是由强加该平台。编译器手册应指定这一点。在托管环境中,选择实际上是在两个给定的参数替代方案之间。如果有参数,这些参数必须正好是两个并且具有给定的类型。顺便说一句,在我看来你错过了*argv
  • 检查标准,您实际上跳过了该部分最后一个短语的延续:“或等效;9) 或以其他一些实现定义的方式。”这意味着这里的编译器实现可能有不同的调用约定。一些编译器,例如允许第三个参数“char *envp[]”。但同样,这必须在编译器文档中指定。
  • C 标准允许main 的返回类型不同于int。 5.1.2.1 的措辞模棱两可,但 5.1.2.2.3 开头是“如果 main 函数的返回类型是与 int ... 兼容的类型”
  • @KeithThompson 5.1.2.1 指定了一个独立的环境,因此它与 5.1.2.2.3 无关,它仅适用于托管环境。是的,该标准允许实现定义的方式来声明 main,以及在返回其他类型而不是 int 时的未指定行为。但是这些仍然是由编译器实现者而不是程序员做出的决定,所以我觉得最好把所有这些特殊情况都排除在这个答案之外。
  • @Lundin:我的意思是,您的回答中有一个事实上不正确的陈述。符合标准的 C 实现可以记录并允许 void main(void)。 (并且您描述的行为不会使 Turbo C 不合格;如果实现没有记录它具有未定义的行为,则定义 void main(),但它不需要诊断。)
【解决方案2】:

Lundin 关于 C 的说法是正确的,但在 C++ 中,措辞足够不同,足以产生影响:

[C++11: 3.6.1/1]: 程序应包含一个名为main 的全局函数,它是程序的指定开始。 独立环境中的程序是否需要定义main函数由实现定义。

[C++11: 3.6.1/2]: 实现不应预定义main 函数。此功能不得重载。 它的返回类型应该是int,否则它的类型是实现定义的[..]

第一个加粗的段落不会覆盖或取消第二个。

main 在 C++ 中总是返回 int

【讨论】:

  • 你可以使用void...除非你不能。
  • 然后 3.6.1/1 继续:“Note: In a freestanding environment, start-up and termination is implementation-defined”。我不知道为什么在 C++11 中更改了措辞,但这只能合理地解释为“独立实现可以完全按照他们的意愿声明 main”。对于没有任何操作系统的程序或操作系统本身来说,返回一个 int 是没有意义的。他们会将 int 归还给谁?
  • @Lundin:启动和终止可能是实现定义的(因此它甚至可能不会发生,或者发生在名为 main 以外的函数的情况下,或者以其他方式发生),但是当存在一个全局main函数时,它的返回类型是int。总是。从明确的措辞中可以看出这一点。
  • @LightnessRacesinOrbit 所以换句话说,独立的 C++ 实现不应该实现 main() ,因为它没用?通常独立系统在一些硬件指定的入口点(“引导扇区”等)启动,从那里基本硬件设置,以及静态初始化等,所有需要在 main() 之前运行的东西。从那里,他们打电话给void main()。你不想回到你的入口点。如果 main 的类型是 int,那么调用约定可能不得不强制将一个无用的垃圾 int 永远保留在堆栈上,这将是愚蠢的。
  • @Lundin:如果一个独立的实现有一个入口函数,他们称之为main,它是全局的,那么它必须有返回类型int。他们可以随意称呼它为void
【解决方案3】:

main 的返回类型由实现决定,而不是程序员。检查您的编译器文档以查看 main 的合法签名是什么。不要以为void main() 就是其中之一。在托管环境中,main 通常返回 int。在独立环境中,入口点甚至可能不命名为main,但其返回类型仍将由实现决定,而不是由程序员决定。

【讨论】:

    【解决方案4】:

    有3种情况:

    1. 独立实施
    2. 符合托管实施,没有扩展
    3. 带有扩展的托管实现

    在 1. 中根本不需要名为 main 的函数。实现定义了程序如何启动。

    在 2. 中,程序开始执行名为 main 的函数,该函数使用以下 2 个“签名”之一定义:int main(void)int main(int argc, char **argv)

    在 3. 中,程序开始在名为 main 的函数处执行,该函数定义为实现所允许的。此函数必须返回 int 以符合标准。例如:int main(int argc, char **argv, char **envp)int main(wchar_t**)。请注意,使用这些形式的程序不一定在所有托管实现中都有效(如果实现发生变化,可能对原作者无效)。

    【讨论】:

    • 在情况 3 中,void main(void) 仍然无效。该标准允许托管实现接受main 的实现定义参数,但不接受不同的返回类型。
    • @R..:谢谢。我已经编辑了我的答案。
    • @R..: C++ 需要main 才能返回int; C 允许实现定义的表单返回其他类型。
    • 好吧,实现可以定义任意数量的超出标准的行为,只要它们不与符合 C 程序的编译或错误报告冲突。例如,gcc 语句表达式({...}) 似乎与语言的任何要求没有冲突,但我会犹豫将使用它们的程序称为“有效 C”,即使它是用于通常使用 gcc 的平台。跨度>
    【解决方案5】:

    最初,在 C 语言中,没有 void 这样的类型,因此函数必须返回 int

    实际上,返回int 允许您从您的进程中运行另一个进程(使用forkexec),如果您可以从该进程中获得返回结果,您将知道它是否有效。

    【讨论】:

      【解决方案6】:

      许多编译器不支持 void main(),因此您应该始终使用 int main()。

      【讨论】:

      • -1 这是错误的。如果您的程序是嵌入式系统或操作系统,它将使用 void main(),这在 C/C++ 标准中非常适用。请在下面进一步查看我的答案。
      • 错误不是因为这个原因,而是因为某些编译器支持的内容与它没有任何关系。
      猜你喜欢
      • 2011-02-22
      • 1970-01-01
      • 2019-02-06
      • 2017-02-03
      • 1970-01-01
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多