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

问题描述 投票:61回答:7

在阅读C ++中的函数时,我被教导函数需要调用声明。例如:

#include <iostream>

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

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

它返回一个错误,因为没有函数sum的声明。

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 forward-declaration function-declaration
7个回答
61
投票

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

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

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

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

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


40
投票

我被教导说函数需要调用声明。

确实。必须先声明一个函数,然后才能调用它。

为什么我们不为main函数添加声明?

好吧,你没有调用main函数。事实上,你不能在all1上调用main,因此在任何事情之前都不需要声明main

从技术上讲,所有定义都是声明,所以你对main的定义也声明了main


脚注1:C ++标准表示从程序中调用main是未定义的行为。

这允许C ++实现将特殊的一次性启动代码放在main的顶部,如果它们不能让它从通常调用main的启动代码中的钩子运行得更早。实际上,一些实际的实现确实这样做,例如,调用快速数学函数,设置一些FPU标志,如非正规零。

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


34
投票

如果你想调用这个函数,那么原型是必需的,但它还没有,比如你的sum

你不能自己打电话给main,所以不需要原型。编写原型甚至是一个坏主意。


25
投票

不,编译器不需要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()的声明。

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

顺便说一句,有时混淆C ++程序是否可以调用main()。不建议这样做。 C ++ 17草案规定main()“不得在程序中使用”。换句话说,不能从程序内调用。参见例如Working Draft Standard for C++ Programming Language, dated "2017-03-21", Paragraph 6.6.1.3, page 66。我意识到一些编译器支持这个(包括我的),但是下一版本的编译器可以修改或删除该行为,因为标准使用术语“不应该”。


10
投票

从程序内部调用main是违法的。这意味着唯一要调用它的是运行时,编译器/链接器可以处理设置。这意味着你不需要main的原型。


7
投票

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

所以写下面的内容也是有效的:

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函数在代码中没有使用/引用,因此无需在任何地方添加main的声明。

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

int main();

int __main() {
  __startup_runtime();

  main();

  __cleanup_runtime();
}

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


5
投票

不。无论如何你不能打电话。

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.