2

これは件名コードです:

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.cppexternfile.cpp

そしてより良い方法で:プロジェクトのコンパイル中にソースファイルはどのように「マージ」されますか(指定する必要がある場合はVS2008を使用)?彼らはどのような「順序」で配置されていますか?そして、それらはどのようにスコープされていますか?

4

3 に答える 3

3

「通常の」VC++プロジェクト1は、各ソースファイルを単独で「オブジェクトファイル」(またはオブジェクトモジュール)にコンパイルするようにVC ++に指示します。コンパイラは、まだ解決されていないシンボル(external変数や関数など)の「プレースホルダー」を残します。宣言されていますが、定義されていません)。

次に、すべてのオブジェクトファイルがリンカーによって結合され、リンカーがそれらを結合して最終的な実行可能ファイルを生成します。このパッセージでは、「プレースホルダー」は、さまざまなオブジェクトファイルで定義されている、参照するコード/データの実際のアドレスに置き換えられます。必要な定義が見つからない場合は未定義の参照エラーが発生し、シンボルが複数回見つかった場合は複数定義エラー2が発生します。

リンクの古典的なモデルの詳細については、 Raymond Chenによるこの記事を参照してください(興味がある場合は、シリーズ全体を参照してください)。


  1. 確かに、もっと柔軟性の余地があります。ここでは、VC++の通常の状況について説明します。
  2. これは、C++の「単一定義規則」の結果です。それでも、これにはいくつかの例外があります。特に、inline関数とtemplateインスタンス化です。そのような場合、リンカは好みのものをそのまま使用します(このようなオブジェクトの複数の定義は同じでなければならないため、問題にはなりません)。
于 2013-01-20T00:58:46.590 に答える
3

IDE VS2008は、ソースファイルをコンパイラに渡します。コンパイラはソースファイルをオブジェクトファイルにビルドし、それらのファイルをリンカに渡します。リンカはこれらのファイルとインクルードをリンクします。

リンカは、dll、lib、exeのいずれであっても、これらすべてのファイルのバイナリ表現を吐き出します。

これは何が起こるかについての非常に基本的な要約であり、進行中のプロセスがさらにあります。

于 2013-01-20T00:59:40.067 に答える
2

これを手動で行う場合、CまたはC++プログラムを実行するには4つのステップがあります。

1-前処理。主にCマクロ、#defineなどを処理します。

2-コンパイルすると、ファイルは外部シンボルのテーブルを含むオブジェクトコードに変換されるため、後で解決できます

3-リンクし、外部参照を解決し、エラーが見つからない場合はエラーを報告します

4-コードを実行します。

これらはすべて、IDEのVS2008によって自動化されています。これらの手順は必要に応じて実行されます。ファイルが変更されていない場合は再コンパイルされません。リンクが必要ない場合は実行されません。.Netでは、アセンブリなどを作成するために必要な手順がさらにあります。

于 2013-01-20T01:04:37.913 に答える