编译时如何处理c ++解决方案源文件?

时间:2013-01-20 00:53:27

标签: c++ compilation linker extern resource-files

这是主题代码:

externfile.cpp

int i = 10;

mainfile.cpp

#include <iostream>

using namespace std;

extern int i;
int main(int param)
{
    cout << i << '\n';
    int i = 0;
    cout << i << '\n';
    cout << ::i << '\n';
}

编译此程序时(使用Visual Studio 2008),它可以正常工作,输出将是:

10
0
10

这对我来说并不奇怪,这是一个范围问题。

但令我困惑的是:mainfile.cpp文件如何从另一个i文件中获取.cpp的值(在我们的案例中为externfile.cpp)?是因为它们位于同一目录中吗?或相同的解决方案?

并以更好的方式:在编译项目时如何“合并”源文件(使用VS2008,如果我应该指定)?在什么“秩序”他们被放置?他们的范围如何?

3 个答案:

答案 0 :(得分:3)

“普通”VC ++项目 1 指示VC ++将每个源文件自身编译为“目标文件”(或对象模块),其中编译器为不符号的符号留下“占位符”尚未解决(如external变量或已声明但未定义的函数。

然后,链接器将所有目标文件绑定在一起,将它们连接在一起以生成最终的可执行文件。在此过程中,“占位符”将替换为各种目标文件中定义的代码/数据的实际地址。如果找不到某些需要的定义,则会得到未定义的引用错误,如果多次找到某个符号,则会出现多重定义错误 2

有关链接的经典模型的更多信息,请查看Raymond Chen的this article(如果您有兴趣,请查看whole series)。


  1. 当然还有更大的灵活性空间,这里我只是描述VC ++中的常见情况。
  2. 这是C ++“一个定义规则”的结果;但是,有一些例外,特别是inline函数和template实例;在这些情况下,链接器只需要它喜欢的任何东西(这不应该是一个问题,因为这些对象的多个定义必须是相同的。)

答案 1 :(得分:3)

您的IDE VS2008将源文件传递给编译器。编译器将源文件构建到目标文件,然后将这些文件传递给链接器,链接器链接这些文件以及包含。

然后链接器会吐出所有这些文件的二进制表示,无论是dll,lib还是exe。

这是对发生的事情的一个非常基本的总结,还有更多的过程。

答案 2 :(得分:2)

如果您手动执行此操作,则运行C或C ++程序将有4个步骤

1 - 预处理,主要处理C宏,#define等。

2 - 编译,文件转换为目标代码,带有外部符号表,以便稍后解决

3 - 链接,解析外部参考,如果找不到任何错误,则报告

4 - 运行代码。

所有这一切都由IDE VS2008自动完成。它会根据需要执行这些步骤,如果文件未更改,则不会重新编译,如果不需要链接,则不会执行此操作。在.Net中,需要更多步骤来制作组件等。