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

Vin*_*sil 63 c++ program-entry-point forward-declaration function-declaration

在阅读有关C ++中的函数的知识时,我被告知函数需要调用声明。例如:

#include <iostream>

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

int sum(int x, int y) {
  return x + y;
}
Run Code Online (Sandbox Code Playgroud)

由于该函数没有声明,因此返回错误sum

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

为了解决这个问题,我将添加声明:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么不为main函数添加声明,而为其他函数添加声明sum呢?

Eri*_*hil 61

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

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

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

在C ++中,用户程序从不调用main,因此在定义之前不需要声明。(请注意,可以根据需要提供一个。关于main这方面的声明没有什么特别的。)在C中,程序可以调用main。在这种情况下,确实需要在调用之前可见声明。

注意,main确实需要调用它的代码知道它。这是通常称为C ++运行时启动代码的特殊代码。当您使用适当的链接器选项链接C ++程序时,链接器会自动为您提供该代码。无论使用哪种语言编写代码,都main需要对其进行声明以正确调用它。


eer*_*ika 41

有人告诉我,函数需要调用声明。

确实。必须先声明一个函数,然后才能对其进行调用。

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

好吧,您没有调用main函数。事实上,你不能调用main所有1,所以从来没有需要申报main才作罢。

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


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

如果C ++实现无法从通常调用的启动代码中的钩子中使它运行得更早,则它们可以将特殊的一次性运行启动代码放在main的顶部main。实际上,某些实际的实现方式确实可以做到这一点,例如,调用设置某些FPU标志(例如反常态为零)的快速数学函数。

在一个假设的实现中,调用main可能会导致有趣的事情,例如重新运行所有静态变量的构造函数,重新初始化new/ delete用来跟踪分配的数据结构或程序的其他整体中断。否则可能根本不会引起任何问题。未定义的行为并不意味着它必须在每个实现上都失败。


Mat*_*her 34

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

您一定不能main自欺欺人,因此不需要原型。编写原型甚至是个坏主意。

  • @Kaz做一些行为未定义的事情是一个坏主意。 (9认同)

Gar*_*ner 25

不,编译器不需要针对的前向声明main()

main() 是C ++中的特殊功能。

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

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

body零个或多个语句在哪里

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

int main (int argc, char* argv[], char *envp[]) { /* body */ }
Run Code Online (Sandbox Code Playgroud)

编码人员必须使用以下可接受的格式之一提供main的“定义”,但编码人员无需提供声明。编译器接受编码后的定义作为main()的声明。

  1. 如果未提供return语句,则编译器将return 0;在函数体内提供a 作为最后一条语句。

顺便说一句,有时对于C ++程序是否可以调用main()感到困惑。不建议这样做。C ++ 17草案指出main()“不得在程序内使用”。换句话说,不能从程序内部调用。参见日期为“ 2017-03-21”的C ++编程语言工作草案标准,第6.6.1.3段,第66页。我意识到有些编译器(包括我的)支持此功能,但是下一版本的编译器可以修改或删除该行为,因为标准使用了“不得”一词。

  • *“编译器不需要为`main()`声明”“ *每个定义都是声明,因此我认为措辞需要调整。*“编译器将其声明为以下两个函数之一” *为什么“编译器声明”?我们总是为自己提供“ main”的定义。 (8认同)
  • 关于(转发)声明的主要功能没有什么特别的。那简直是红鲱鱼。相反,我们不需要转发声明它,因为我们在定义它之前没有引用它。就这样。 (6认同)

Nat*_*ica 10

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


t.n*_*ese 7

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

因此,编写以下内容也是有效的:

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

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

如果在一个文件中使用一个声明使编译器在定义函数之前就知道该函数,则必须在链接时知道其定义:

main.cpp

int sum(int x, int y);

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

sum.cpp

int sum(int x, int y) {
  return x + y;
}
Run Code Online (Sandbox Code Playgroud)

或者它sum可能起源于库,因此您甚至不必自己编译它。

main函数未在代码中的任何地方使用/引用,因此不需要在main任何地方添加声明。

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

int main();

int __main() {
  __startup_runtime();

  main();

  __cleanup_runtime();
}
Run Code Online (Sandbox Code Playgroud)

但是随后您又遇到了同样的问题,__main因此在某些时候不再有c ++,并且某个函数(main)只是表示代码的入口点。


Jos*_*hua 5

不。无论如何你都不能称呼它。

您只需要在定义函数之前就对其进行正向声明。对于其他文件中定义的函数,您需要外部声明(看起来像故意的前向声明)。

但是您不能main使用C ++进行调用,因此您不需要一个。这是因为允许C ++编译器修改main来进行全局初始化。

[我看了看crt0.c,它确实有main的声明,但是这里和那里都没有]。

  • @CruzJean不仅是一种不好的做法,据我所知这是未定义的行为 (8认同)
  • @CruzJean不错的做法。调用它会调用未定义的行为。 (5认同)