这是主题代码:
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,如果我应该指定)?在什么“秩序”他们被放置?他们的范围如何?
答案 0 :(得分:3)
“普通”VC ++项目 1 指示VC ++将每个源文件自身编译为“目标文件”(或对象模块),其中编译器为不符号的符号留下“占位符”尚未解决(如external
变量或已声明但未定义的函数。
然后,链接器将所有目标文件绑定在一起,将它们连接在一起以生成最终的可执行文件。在此过程中,“占位符”将替换为各种目标文件中定义的代码/数据的实际地址。如果找不到某些需要的定义,则会得到未定义的引用错误,如果多次找到某个符号,则会出现多重定义错误 2 。
有关链接的经典模型的更多信息,请查看Raymond Chen的this article(如果您有兴趣,请查看whole series)。
inline
函数和template
实例;在这些情况下,链接器只需要它喜欢的任何东西(这不应该是一个问题,因为这些对象的多个定义必须是相同的。)答案 1 :(得分:3)
您的IDE VS2008将源文件传递给编译器。编译器将源文件构建到目标文件,然后将这些文件传递给链接器,链接器链接这些文件以及包含。
然后链接器会吐出所有这些文件的二进制表示,无论是dll,lib还是exe。
这是对发生的事情的一个非常基本的总结,还有更多的过程。
答案 2 :(得分:2)
如果您手动执行此操作,则运行C或C ++程序将有4个步骤
1 - 预处理,主要处理C宏,#define等。
2 - 编译,文件转换为目标代码,带有外部符号表,以便稍后解决
3 - 链接,解析外部参考,如果找不到任何错误,则报告
4 - 运行代码。
所有这一切都由IDE VS2008自动完成。它会根据需要执行这些步骤,如果文件未更改,则不会重新编译,如果不需要链接,则不会执行此操作。在.Net中,需要更多步骤来制作组件等。