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
函数。事实上,你根本不能调用 main
1,所以永远不需要在任何事情之前声明 main
。
虽然从技术上讲,所有定义也是声明,因此您对 main
的定义也声明了 main
.
脚注 1:C++ 标准规定从程序内部调用 main
是未定义的行为。
这允许 C++ 实现将特殊的 运行-once 启动代码放在 main 的顶部,如果它们无法从启动代码中的挂钩中获得它 运行调用 main
。一些真正的实现实际上是这样做的,例如调用一个设置一些 FPU 标志的快速数学函数,如非正规数为零。
在假设的实现中,调用 main 可能会导致有趣的事情,例如重新运行所有静态变量的构造函数,重新初始化 new
/[=19= 使用的数据结构] 以跟踪分配或程序的其他总中断。或者它可能根本不会造成任何问题。未定义的行为并不意味着它必须在每次实施时都失败。
不,编译器不需要 main()
.
的前向声明
main()
是C++中的一个特殊函数。
关于 main() 需要记住的一些重要事项是:
- 链接器要求在创建可执行程序时只有一个
main()
函数存在。
- 编译器需要以下两种形式之一的 main() 函数:
int main () { /* body */ }
int main (int argc, char *argv[]) { /* body */ }
其中 body
是零个或多个语句
另一种可接受的形式是特定于实现的,并提供调用函数时的环境变量列表:
int main (int argc, char* argv[], char *envp[]) { /* body */ }
编码者必须使用这些可接受的形式之一提供 main 的 'definition',但编码者不需要提供声明。编译器接受编码定义作为 main() 的声明。
- 如果没有提供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
) 只是代表你的代码的入口点。
有人告诉我函数需要声明才能被调用。为了说明,下面的例子会给我一个错误,因为没有函数 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
函数。事实上,你根本不能调用 main
1,所以永远不需要在任何事情之前声明 main
。
虽然从技术上讲,所有定义也是声明,因此您对 main
的定义也声明了 main
.
脚注 1:C++ 标准规定从程序内部调用 main
是未定义的行为。
这允许 C++ 实现将特殊的 运行-once 启动代码放在 main 的顶部,如果它们无法从启动代码中的挂钩中获得它 运行调用 main
。一些真正的实现实际上是这样做的,例如调用一个设置一些 FPU 标志的快速数学函数,如非正规数为零。
在假设的实现中,调用 main 可能会导致有趣的事情,例如重新运行所有静态变量的构造函数,重新初始化 new
/[=19= 使用的数据结构] 以跟踪分配或程序的其他总中断。或者它可能根本不会造成任何问题。未定义的行为并不意味着它必须在每次实施时都失败。
不,编译器不需要 main()
.
main()
是C++中的一个特殊函数。
关于 main() 需要记住的一些重要事项是:
- 链接器要求在创建可执行程序时只有一个
main()
函数存在。 - 编译器需要以下两种形式之一的 main() 函数:
int main () { /* body */ }
int main (int argc, char *argv[]) { /* body */ }
其中 body
是零个或多个语句
另一种可接受的形式是特定于实现的,并提供调用函数时的环境变量列表:
int main (int argc, char* argv[], char *envp[]) { /* body */ }
编码者必须使用这些可接受的形式之一提供 main 的 'definition',但编码者不需要提供声明。编译器接受编码定义作为 main() 的声明。
- 如果没有提供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
) 只是代表你的代码的入口点。