【问题标题】:How are c++ solution source files dealt while being compiled?c++ 解决方案源文件在编译时如何处理?
【发布时间】:2013-01-20 00:53:27
【问题描述】:

这是主题代码:

externfile.cpp

int i = 10;

ma​​infile.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 文件如何从另一个.cpp 文件(在我们的例子中为externfile.cpp)获取i 的值?仅仅是因为它们位于同一个目录中吗?还是同样的解决方案?

还有一种更好的方式:编译项目时如何“合并”源文件(如果我应该指定,使用 VS2008)?它们按什么“顺序”排列?它们的范围如何?

【问题讨论】:

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


【解决方案1】:

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

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

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


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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 值得注意的是,源文件是完全独立编译的。只有链接器才能将各个部分组合在一起。
    【解决方案3】:

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

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

    2 - 编译,文件被转换为带有外部符号表的目标代码,以便以后解决这些问题

    3 - 链接,解决外部引用,如果找不到则报告任何错误

    4 - 运行代码。

    所有这些都由 IDE VS2008 自动完成。它使这些步骤根据需要进行,如果文件没有更改,则不会重新编译,如果不需要链接,则不会完成。在 .Net 中,制作程序集等需要更多步骤。

    【讨论】:

      猜你喜欢
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-28
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 2020-09-05
      相关资源
      最近更新 更多