GCC通过输入源代码进行了多少次通过



按照此答案,现代编译器只需进行一次通过即可。假设GCC是现代的,为什么以下简单程序会给我一个错误,说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";
}

我知道,通过在main()上方的test()的函数原型中可以轻松解决此错误;或通过在main()之前声明和定义test()。但是,我不是要求解决方法 - 我问为什么编译器未检测到我在程序的稍后阶段声明并定义了test()?p>从我在学校学到的知识中,许多召集人两次解析了输入代码;但是,如果GCC(也许是它的汇编器?(是否仅一次,那么为什么不考虑这样的 forward参考?或者,我错过了什么吗?

谢谢。

注意:cpp.sh确实在此处指出。

编辑:根据C 规则,我们需要在使用这些内容之前声明这些内容。如果(以及何时(汇编器确实通过了1,请找出(并记下(已声明的内容(在这种情况下为test()(,然后在以后在Pass 2中使用它来解决明显的前进参考?或者,此责任不是不在汇编器吗?

它不起作用的原因是,因为它只能通过。要支持使用后定义的函数,它必须进行两个通过:通过1查找所有功能签名,通过2检查对所有签名的调用,以确定是否定义了函数。

c 的规范是在牢记的,这就是为什么它需要在引用之前定义所有功能和类的原因。

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

c 更为复杂,因为名称可以参考函数或类,如果它是一个函数,则可以有多个过载。解析名称的使用取决于其名称的名称,因此离开占位符直到找到定义并不是可行的。

c 语言比您想象的要复杂得多……例如,确实执行了这种"向前看"的情况:

struct Foo {
    void baz() {
        bar(); // ok, even if bar comes later
    }
    void bar() {
        printf("Hello, world.n");
    }
};

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

认为C 甚至具有如此复杂烦人的解析"规则(。

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

最新更新