int main() 是否需要在 C++ 上声明?

Does int main() need a declaration on C++?

有人告诉我函数需要声明才能被调用。为了说明,下面的例子会给我一个错误,因为没有函数 sum:

的声明
#include <iostream>

int main() {
  std::cout << "The result is " << sum(1, 2);
  return 0;
}

int sum(int x, int y) {
  return x + y;
}

// main.cpp:4:36: error: use of undeclared identifier 'sum'
//  std::cout << "The result is " << sum(1, 2);
//                                   ^
// 1 error generated.

要解决此问题,我将添加声明:

#include <iostream>

int sum(int x, int y); // declaration

int main() {
  std::cout << "The result is " << sum(1, 2);
  return 0;
}

int sum(int x, int y) {
  return x + y;
}

为什么 main 函数不需要声明,而 sum 等其他函数需要声明?

没有。无论如何都不能调用它。

您只需要在函数定义之前对调用的函数进行前向声明。对于在其他文件中定义的函数,您需要外部声明(故意看起来与前向声明完全一样)。

但是你不能在 C++ 中调用 main 所以你不需要一个。这是因为允许C++编译器修改main来做全局初始化。

[我查看了 crt0.c,它确实有一个 main 声明,但它既不存在也不存在]。

如果您想调用该函数,则需要原型,但它尚不可用,例如您的情况 sum

你不能自己调用​​main,所以不需要有原型。甚至写一个原型也是个坏主意。

从您的程序内部调用 main 是非法的。这意味着唯一要调用它的是运行时,compiler/linker 可以处理设置 up.This 意味着你不需要 main.

的原型

I was taught that functions need declarations to be called.

确实如此。函数必须在调用前声明。

why we don't add a declaration for the main function?

嗯,你没有调用 main 函数。事实上,你根本不能调用 main1,所以永远不需要在任何事情之前声明 main

虽然从技术上讲,所有定义也是声明,因此您对 main 的定义也声明了 main.


脚注 1:C++ 标准规定从程序内部调用 main 是未定义的行为。

这允许 C++ 实现将特殊的 运行-once 启动代码放在 main 的顶部,如果它们无法从启动代码中的挂钩中获得它 运行调用 main。一些真正的实现实际上是这样做的,例如调用一个设置一些 FPU 标志的快速数学函数,如非正规数为零。

在假设的实现中,调用 main 可能会导致有趣的事情,例如重新运行所有静态变量的构造函数,重新初始化 new/[=19= 使用的数据结构] 以跟踪分配或程序的其他总中断。或者它可能根本不会造成任何问题。未定义的行为并不意味着它必须在每次实施时都失败。

不,编译器不需要 main().

的前向声明

main()是C++中的一个特殊函数。

关于 main() 需要记住的一些重要事项是:

  1. 链接器要求在创建可执行程序时只有一个 main() 函数存在。
  2. 编译器需要以下两种形式之一的 main() 函数:
int main () { /* body */ } 
int main (int argc, char *argv[]) { /* body */ } 

其中 body 是零个或多个语句

另一种可接受的形式是特定于实现的,并提供调用函数时的环境变量列表:

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

编码者必须使用这些可接受的形式之一提供 main 的 'definition',但编码者不需要提供声明。编译器接受编码定义作为 main() 的声明。

  1. 如果没有提供return语句,编译器将提供一个return 0;作为函数体中的最后一个语句。

顺便说一句,有时会混淆 C++ 程序是否可以调用 main()。不推荐这样做。 C++17 草案规定 main() "shall not be used within a program." 换句话说,不能从程序内部调用。参见例如Working Draft Standard for C++ Programming Language, dated "2017-03-21", Paragraph 6.6.1.3, page 66。我知道有些编译器支持这个(包括我的),但是下一版本的编译器可以修改或删除该行为,因为标准使用术语 "shall not".

函数的定义也是函数的声明。

声明函数的目的是让编译器知道它。声明一个函数而不定义它允许在不方便定义它的地方使用一个函数。例如:

  • 如果一个函数在源文件(A)中使用而不是在(B)中定义的,我们需要在A中声明它(通常通过A包含的头文件,例如B.h).
  • 如果两个或多个函数可以相互调用,那么我们不能在其他函数之前定义所有这些函数——其中一个函数必须先定义。因此可以先提供声明,再提供定义。
  • 许多人更喜欢将“更高级别”的例程放在源文件的前面,然后将子例程放在后面。由于那些“更高级别”的例程调用各种子例程,因此必须更早地声明子例程。

在 C++ 中,用户程序永远不会调用 main,因此它永远不需要在定义之前声明。 (请注意,如果您愿意,可以提供一个。在这方面声明 main 没有什么特别之处。)在 C 中,程序可以调用 main。在那种情况下,它确实要求声明在调用之前可见。

请注意,调用它的代码确实需要知道 main。这是通常称为 C++ 运行时启动代码的特殊代码。当您使用适当的链接器选项链接 C++ 程序时,链接器会自动为您包含该代码。无论代码是用什么语言编写的,它都有任何 main 的声明,以便正确调用它。

函数的定义也隐式声明了它。如果您需要在函数定义之前引用它,您需要在使用它之前声明它。

所以这样写也是有效的:

int sum(int x, int y) {
  return x + y;
}

int main() {
  std::cout << "The result is " << sum(1, 2);
  return 0;
}

如果您在一个文件中使用声明使编译器在定义函数之前就知道它,那么它的定义必须在链接时知道:

main.cpp

int sum(int x, int y);

int main() {
  std::cout << "The result is " << sum(1, 2);
  return 0;
}

sum.cpp

int sum(int x, int y) {
  return x + y;
}

或者 sum 可能起源于一个库,所以你甚至不需要自己编译它。

main 函数不在您代码中的任何地方 used/referenced,因此无需在任何地方添加 main 的声明。

在您的 main 函数之前和之后,c++ 库可能会执行一些初始化和清理步骤,并将调用您的 main 函数。如果库的那部分将表示为 c++ 代码,那么它将包含 int main() 的声明,以便可以对其进行编译。该代码可能如下所示:

int main();

int __main() {
  __startup_runtime();

  main();

  __cleanup_runtime();
}

但是你又遇到了与 __main 相同的问题,所以在某些时候不再有 c++,某个函数 (main) 只是代表你的代码的入口点。