31

このコードは正常にコンパイルされます:

extern int i = 10;

void test()
{
    std::cout << "Hi" << i << std::endl;
}

このコードはエラーを出しますが:

void test()
{
    extern int i = 10;
    std::cout << "Hi" << i << std::endl;
}

エラー: 'i' には 'extern' と初期化子の両方があります

私はC++ Primerでこれを読みました:

明示的な初期化子を含む宣言はすべて定義です。extern として定義された変数に初期化子を提供できますが、そうすると extern がオーバーライドされます。初期化子を持つ extern は定義です。関数内の extern に初期化子を指定するとエラーになります

同じことがグローバルスコープで許可されているのに、関数でローカルに実行された場合にこれがエラーになる理由について誰かが説明できますか?

4

5 に答える 5

25

関数内で外部変数を定義することが意味をなさない理由は次のとおりです。

シンボル extern を宣言すると、この値が出現するすべての箇所を同じシンボルにリンクするようコンパイラに指示することになります。extern int i; の出現。あなたのプログラムでは、外部で定義された i にリンクします。この例を見てください:

#include <iostream>
using namespace std;

extern int i;
int i = 10;
void test()
{
    std::cout << "Hi" << i << std::endl;
}

int main()
{
    extern int i;
    i++;
    test();
}

この例では、hi11 が出力されます。ただし、main 内の extern を削除すると、10 が出力されます。これは、extern がないと、i がグローバル i にリンクせず、i の独自のローカル コピーを作成するためです。

関数内で extern i を定義することが意味をなさない理由は、どの関数でも i を「定義」できるようにするとどうなるかということです。最初に実行される関数はどれですか? いつ定義されますか?

次の例が有効であると仮定すると、出力はどうなるでしょうか???

#include <iostream>
using namespace std;

extern int i;
int i = 10;
void test()
{
    std::cout << "Hi" << i << std::endl;
}

void test2() {
    extern int i = 1000;
    std::cout<< "HI" << i << std::endl;
}

void test3() {
    extern int i;
    i = 1000;
    std::cout<< "HI" << i << std::endl;
}

int main()
{
    extern int i;
    i++;
    test();
    i = 0;
    test2();
}

test2 の出力は 0 か 1000 か? また、私の test3 を見てください。ここでは、私の i を外部で定義された i にリンクし、その値を 1000 として割り当てます。これは、値を「初期化」しようとすることとは大きく異なります。

要するに、extern 変数は実際にはグローバルとしてのみ意味があり、グローバル スコープで定義する必要があります。あなたの例では、最初のバージョンもコンパイルされません。これは面白いと思います。これが簡潔に定義されているかどうか、または追加の保護を追加するように設計された方法でコンパイラがこれを処理している可能性があるかどうかを確認するには、標準ドキュメントを調べる価値があるかもしれません...

于 2013-06-13T15:16:31.433 に答える
0

それを置く最も簡単な方法:

externキーワードの目的は、オブジェクトを定義せずに宣言することです。それを定義することで、基本的にコンパイラに「値を代入するのではなく、値を代入する」ように伝えています。それは意味がありません-関数の内外で決して実行しないでください。ほとんどのコンパイラは、警告を出して続行するか、まったくコンパイルせずにエラーを出します。

この質問の範囲を超えて詳細を説明すること externはできませんが、この質問の回答を読むと役立つ場合があります。

于 2015-05-23T01:20:56.357 に答える