编译器从哪里开始读取

Suh*_*pta 2 c++ visual-c++

这是一个小程序:

#include <iostream>
using namespace std;

int main() {
    f();
    system("pause");
}

void f() {
    static int x = 20 ;
    class tester {
    public :
        tester() {
            cout << x ;
        }
    } x1;
}
Run Code Online (Sandbox Code Playgroud)

我在这里得到的错误是:错误C3861:'f':找不到标识符

如果我将函数f置于main之上,我将获得所需的输出.

为什么会这样? 我被告知程序执行开始于main.据此,代码也应该在第一种情况下运行.

编译器如何开始阅读程序?

nic*_*ico 7

我被告知程序执行从main开始.

而这正是重点.

编译器从main,然后看到一个调用f(),到目前为止它没有遇到过(因为它是后来定义的),所以它不知道如何处理它.

如果你想fmain之前放置一个函数原型之后定义,比如

#include <iostream>
using namespace std;

void f(); // <--- This tells the compiler that a function name f will be defined

int main() {
f();
system("pause");
}

void f() {
static int x = 20 ;
class tester {
public :
    tester() {
        cout << x ;
    }
} x1;
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*lia 6

编译的开始和程序执行的开始是两回事.

执行从main.

编译从文件的开头开始; 编译器不会"跳转"文件以找到所需的部分,但它以线性方式读取输入(我怀疑这与C++语法真正复杂的事实相关).

当编译器在某个时刻解析文件时,它只知道在该点1之前声明/定义的内容.

因此,已经发明了函数原型(以及一般的非定义声明):文件中定义的所有函数的原型都放在文件的开头,通常在#include指令之后或在单独的包含文件中.原型告诉编译器这些函数将在稍后定义,函数签名是什么(即名称,参数,返回值).

原型是作为正常功能制作的,但没有身体,而是用分号2代替.例如,在你的代码中你会写

void f();
Run Code Online (Sandbox Code Playgroud)

之前main.


  1. IIRC对此规则有一些放松,允许编译器"等待"一些声明来使模板魔术工作,但这与此无关.

  2. 在原型中也常见的是不写参数的名称,只留下它们的类型(这也可以在函数定义中完成,但除非你有一个不使用的形式参数,否则它没有多大意义) .不过,我更喜欢将参数名称留在那里作为一种文档形式.