2

2 つの cpp ファイルと 1 つのヘッダー ファイルがあり、両方の cpp ファイルに含まれています。こんな感じです:

abc.h

extern uint32_t key;

a.cpp

#include "abc.h"
uint32_t key;
int main
{
.............
}

b.cpp

#include "abc.h"

int main
{
printf("Key: %.8x\n", key);
.............
}

a.cpp をコンパイルすると、エラーは発生しなくなりました。しかし、b.cpp をコンパイルすると、「'key' への未定義の参照」というエラーが表示されます。このコードの問題を見つけるのを手伝ってください。

4

6 に答える 6

9

変数を共有するには、通常、次のようなものがあります。

// A.h
extern int key;
void show();

//a.cpp
#include "a.h"

int main() { 
    key = 1;
    show();
};

// b.cpp
#include "a.h"
#include <iostream>

int key;

void show() { std::cout << "Key = " << key; }

ここで注意すべき点がいくつかあります。まず、extern宣言をヘッダーに入れ、変数を使用するすべてのファイルに含めます。extern変数 ( なし) を 1 つのファイルだけで定義します。という名前の関数を含むファイルは 1 つだけにしてくださいmain

編集: これをビルドするには、各ファイルを単独でコンパイルしますが、2 つのファイルをリンクする必要があります。たとえば、gcc を使用すると、次のようなことができます。

gcc -c a.c
gcc -c b.c
gcc a.o b.o

1 つ目は ac をコンパイルします (ただし、リンクしません) 2 つ目は bc で同じことを行います 3 つ目は実際に 2 つを一緒にリンクし、実行可能なバイナリ イメージを生成します (伝統的には という名前a.outですが、たとえば Windows では通常 に変更されますa.exe)。

于 2010-05-24T17:26:27.563 に答える
3

問題は、まさにエラー メッセージの内容です。Abc.hは変数を宣言していますが、定義していません。a.cpp の行で定義されています。つまり、a.cpp は、変数の物理ストレージが表示される場所です。b.cpp にはそのような行がないため、そのプログラムをコンパイルしようとすると、リンカはその変数に対して定義されたストレージを持たないままになります。

ヘッダーで「extern」指定子を省略した場合、b.cpp は正常にコンパイルされますが、a.cpp は複数の定義に関するエラーを返す可能性があります。

「extern」指定子は、1 つのプログラムに複数のソース ファイルがある場合に、より大きな役割を果たします。その場合、それらはすべて abc.h を含む可能性がありますが、「extern」がなければ、コンパイルされた各オブジェクト ファイルは、同じ変数の独自の独立した定義を持つことになります。リンカは通常、それをどうするか分からず、おそらく不平を言うでしょうが、そうする必要はないと思います. 修正は、「extern」を使用して、コンパイルされた各ファイル file に宣言のみが含まれるようにすることです。次に、定義を配置するソース ファイルを1 つ選択します。宣言は abc.h にあるため、おそらく abc.cpp に配置します。

于 2010-05-24T17:30:40.767 に答える
2

ヘッダーファイルの行は宣言です; 変数が存在することをコンパイラに通知しますが、その変数にスペースを割り当てません。1つ以上のソースファイルからプログラムをビルドする場合、そのうちの1つに定義も含まれている必要があります。

あなたの場合、あなたはに定義を持っているa.cppので、それはプログラムを構築するために必要なすべてを含んでいます。b.cpp定義がないため、リンクに失敗します。

2つの解決策があります。定義をからにコピーするかa.cppb.cppそれを3番目のソースファイルに移動して、両方のプログラムをビルドするときにソースのリストに含めます。

于 2010-05-24T17:36:59.710 に答える
2

2 つの別個のプログラムをコンパイルしています。一方が他方から変数を参照することはできません。externキーワードは、リンクされている同じ実行可能ファイルの別のオブジェクトファイル内の 1 つのオブジェクト ファイルからシンボルを参照するためのものです。

于 2010-05-24T17:33:07.130 に答える
1

リンクエラーが発生していると思いますか?b をリンクするときは ao を含める必要がありますが、a と b の両方に実際に「main」がある場合は機能しません。key を宣言する c.cpp を作成し、co を a.exe と b.exe の両方にリンクする必要があります。

于 2010-05-24T17:30:29.100 に答える
0

との両方a.cppに関数が定義されb.cppており、プログラムごとmain()に 1 つしか定義できません。main()したがって、あなたがやろうとしているのは、2 つのプログラム間でヘッダー ファイルを共有することだと思います。その場合は、次の行を追加しb.cppて定義keyおよび再コンパイルします。

uint32_t key;

これは、ヘッダー ファイルを使用する通常の方法ではありません。代わりにkey、パラメーターとして受け取る関数を記述します。このようにすると、グローバル変数が設定されますが、これは一般的に嫌われています。

externほとんどの場合、グローバル変数を設定するために使用されます (頭の中で、 を使用する他の理由は考えられませんextern)。しかし、通常の方法で使用したい場合はextern(使用する必要があるかどうかにはまったく触れずに)、次のようにします。

  • 2 つのファイルの 1 つから関数を削除します。main()この回答では、から削除しますb.cpp
  • 次の 2 行を使用して、プログラムをコンパイルおよびリンクします (gcc を想定)。

    gcc -c -o b.o b.cpp

    gcc a.cpp b.o

(最初の行)への-cオプションは、「コンパイルのみ、リンクしない」と言います。すべての変数が定義されているかどうかを判断するのはリンク手順であり、コンパイル時には定義されていませんが、コンパイル時には定義されています(2 行目)。gccb.cppa.cpp

于 2010-05-24T17:53:17.923 に答える