gcc对输入源代码的传递次数是多少?

时间:2018-02-06 21:55:33

标签: c++ gcc g++

根据这个SO答案,现代编译器只进行一次传递。假设GCC是现代的,为什么following simple program给我一个错误,说明test()未在此范围内声明:

// Example program
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string str="Naggy";
    test(str);

    cout<<str<<"\n";
}

void test(string& str) {
    str="Rathore";
}

我知道通过test()以上main()的函数原型可以轻松解决此错误;或者在test()之前声明并定义main()。但是,我要求解决方法 - 我问为什么编译器没有检测到我已经声明并定义了test()程序

从我在学校学到的记忆中,许多装配工解析输入代码两次;但是如果GCC(也许是它的汇编程序?)只执行一次,那么为什么不考虑这样的前向引用呢?或者,我错过了什么?

感谢。

注意:cpp.sh确实使用GCC,如注明here

编辑:根据C ++规则,我们需要在使用之前声明这些内容。如果(和何时)汇编程序传递1,它是否找不到(并记下)已声明的东西(在本例中为test()),然后在第2遍中使用解决明显的前向参考?或者,这个责任 NOT 是否与汇编程序有关?

2 个答案:

答案 0 :(得分:1)

它不起作用的原因是因为它只进行一次通过。为了支持在使用后定义的函数,它必须进行两次传递:Pass 1查找所有函数签名,pass 2检查对所有签名的调用以确定函数是否已定义。

C ++的规范是为此而编写的,这就是为什么它要求在引用之前定义所有函数和类。

汇编程序通常能够通过单次传递处理前向引用,因为语言更简单。当他们遇到未知标识符时,他们不需要知道它的声明是什么 - 它只是一个地址。他们可以在输出数据中留下占位符,当他们到达定义时,他们可以更新占位符。

C ++更复杂,因为名称可以引用函数或类,如果它是函数,则可能存在多个重载。解析名称的使用取决于它的名称,因此在找到定义之前留下占位符是不可行的。

答案 1 :(得分:1)

C ++语言比你想象的复杂得多......例如,有些情况下,如果确实执行了“向前看”这样的话:

True

编译器在您的情况下给出错误,因为C ++规则说明了这一点。 C ++的许多部分都是合乎逻辑的,但许多部分也根本不符合逻辑。

考虑到C ++甚至有一个如此复杂的规则,它要求编译器在确定第一个令牌的语义含义之前阅读无限数量的令牌(可怕的“{ {3}}“规则”。

使用C ++有时只是学习规则的唯一安全方法:不要太努力总是找不到逻辑,可能没有。