1

AFAIK、externキーワードを宣言に使用する必要があり、externキーワードで宣言されている変数に値を関連付けることはできません。しかし、私が次のようなステートメントを書いたとすると

extern int i = 10;

コンパイラは同じエラーにフラグを立てる必要がありますか?一部のコンパイラが耐性があり、これを無視しているのを見たことがありますか?なんでそうなの?「C」規格はこれについて何と言っていますか?

編集:@ All、回答ありがとうございます。私はまだ疑問があります。acなどの別のファイルにexternリンケージのないこの変数の定義があり、このステートメントをbcに追加するとします。それでも、コンパイラーがエラーのフラグを立てなくても大丈夫ですか?再定義されますか?

4

4 に答える 4

5

これは有効な構文であり、C99標準には本質的に同じ例もあります。(§6.9.2-4を参照してください。)

確かに例は規範的ではありませんが、それは合法的な構文であることが意図されていたと思います。コンパイラは実際には何も実行しないため、警告を出力することがよくあります。

4例1

int i1 = 1;             // definition, external linkage
static int i2 = 2;      // definition, internal linkage
extern int i3 = 3;      // definition, external linkage
int i4;                 // tentative definition, external linkage
static int i5;          // tentative definition, internal linkage
int i1;                 // valid tentative definition, refers to previous
int i2;                 // 6.2.2 renders undefined, linkage disagreement
int i3;                 // valid tentative definition, refers to previous
int i4;                 // valid tentative definition, refers to previous
int i5;                 // 6.2.2 renders undefined, linkage disagreement
extern int i1;          // refers to previous, whose linkage is external
extern int i2;          // refers to previous, whose linkage is internal
extern int i3;          // refers to previous, whose linkage is external
extern int i4;          // refers to previous, whose linkage is external
extern int i5;          // refers to previous, whose linkage is internal
于 2010-02-27T19:59:45.877 に答える
4

次のコード;

extern int i ;

変数iを宣言しますが、インスタンス化しません。同じコンパイルユニットでも定義されていない場合、リンカは最終的な実行可能ファイルを構成するオブジェクトファイルとライブラリから解決しようとします。

しかしあなたの例:

extern int i = 10 ;

オブジェクトを初期化するため、インスタンス化する必要もあります。この場合、externオブジェクトは同じコンパイル単位(実際には同じステートメント)で初期化されるため、キーワードは冗長です。これは次と同等です。

extern int i ;  // redundant
int i = 10 ;

この最後の例では、externキーワードは冗長ですが、グローバル変数がヘッダーファイルで宣言され、そのヘッダーも含むソースファイルでインスタンス化された場合とまったく同じです(コンパイラーを許可するために必要です)。タイプチェックを実行します)。

これは次のようにテストできます。

extern int i ;
int main()
{
    i = 10 ;
}

上記の場合、未解決の変数iに対してリンカーエラーが発生します。一方:

extern int i = 10 ;
int main()
{
    i = 10 ;
}

問題なくリンクします。

于 2010-02-27T23:42:46.530 に答える
0

キーワードは、extern指定された変数が別のモジュールに割り当てられていることを示します。その変数へのアクセスとは何の関係もありません。extern変数に割り当てるために割り当てることは完全に合法です。

于 2010-02-27T20:00:40.703 に答える
-1

キーワードの目的は、エンティティに外部リンクexternを与えることです。の宣言で使用されているか、定義で使用されているかは関係ありません。投稿したコードにエラーはまったくありません。

「エクスポートとインポート」の観点から考える場合、非定義宣言externに適用されるキーワードは、他の翻訳単位で定義されたエンティティをインポートしていることを意味します。キーワードを定義に適用すると、他の翻訳単位で使用するためにこのエンティティをエクスポートすることを意味します。(ただし、「エクスポートとインポート」は、Cリンケージの概念についての標準的な考え方ではないことに注意してください。)extern

定義で使用されるキーワードが頻繁に表示されない理由は、Cファイルスコープの定義にはデフォルトで外部リンケージがあるためです。だから書く

extern int i = 10;

有効ですが、プレーンと同等であるため冗長です

int i = 10;

それでも、実際のコードでは、このキーワードが不要であるにもかかわらず、関数の宣言と定義でこのキーワードを使用している人がいることがあります。

extern void foo(int i); /* `extern` is superfluous */
...
extern void foo(int i) /* `extern` is superfluous */
{
  /* whatever */
}
于 2010-02-27T20:05:12.907 に答える