5

main.h

extern int array[100];

main.c

#include "main.h"

int array[100] = {0};

int main(void)
{
    /* do_stuff_with_array */ 
}

main.c モジュールでは、配列が定義され、宣言されています。モジュールに extern ステートメントを含める行為は、何か問題を引き起こしますか?

私は常にexternステートメントをリンカーへのコマンドとして視覚化し、「実際の名前付きエンティティを他の場所で探します。ここにはありません。

私は何が欠けていますか?

ありがとう。

悪の。

4

5 に答える 5

26

の正しい解釈は、コンパイラexternに何かを伝えることです。宣言された変数は、現在存在していなくても、何らかの方法でリンカによって (通常は別のオブジェクト (ファイル) で) 検出されることをコンパイラに伝えます。リンカは、extern 宣言があるかどうかに関係なく、すべてを見つけてまとめられる幸運な人です。

特定のオブジェクト (ファイル) の外部に名前 (変数、関数、..) が露出するのを避けるには、static.

于 2009-03-25T19:58:52.800 に答える
9

いえ、無害です。実際、これはあなたが望むことを行うためのかなり標準的な方法だと思います。

ご存じのとおり、これは、main.h を含む .c ファイルもそれを表示arrayおよびアクセスできることを意味します。

于 2009-03-25T19:54:56.523 に答える
6

編集

C と C++ の両方で、 の存在はextern、最初の宣言が定義ではないことを示します。したがって、現在の翻訳単位 (ヘッダーをインクルードするすべてのユーザー) で名前を使用できるようにし、参照されるオブジェクトに外部リンケージがあることを示します。つまり、プログラムを構成するすべての翻訳単位で使用できます。オブジェクトが必ずしも別の翻訳単位にあると言っているのではなく、「この行は定義ではない」というだけです。

編集を終了

C では、externはオプションです。それがなければ、最初の宣言は「暫定的な定義」です。後の定義 (初期化子があるため、明確に定義です) がなければ、これは定義として扱われます (C99 6.9.2)。このままでは単なる宣言であり、競合しません。

C++ では、externはオプションではありません。これがないと、最初の宣言が定義 (C++03 3.1) になり、2 番目の宣言と競合します。

この違いは、C++ の Annex C で明示的に指摘されています。

「変更: C++ には、C のような「仮の定義」がありません。

たとえば、ファイル スコープでは、

int i;
int i;

C では有効ですが、C++ では無効です。」

于 2009-03-25T22:46:46.763 に答える
4

extern は無害で正しいです。extern なしではヘッダーで宣言できませんでした。

さらに、通常は、配列のサイズを保持するマクロまたは定数を作成することをお勧めします。コードでは、実際のサイズ (100) がソース ベースに 2 回表示されます。次のようにすると、よりクリーンになります。

#define ARRAY_SIZE 100

extern int array[ARRAY_SIZE];

...

int array[ARRAY_SIZE] = { 0 };

しかし、簡潔にするためだけにこれをコード スニペットに含めたくなかったので、気分を害しないでください :)

于 2009-03-25T20:46:46.617 に答える
1

コンパイルまたは実行の観点からは、違いはありません。

ただし、それによって array[] が main.h を #include する他のファイルで使用可能になり、別のファイルで array[] の内容が変更される可能性があるため、潜在的に危険です。

したがって、array[] が main.c でのみ使用される場合は、main.h からその行を削除し、main.c で array[] を static として宣言します。

array[] が main() 関数でのみ使用される場合は、そこで宣言します。

つまり、array[] のスコープは可能な限り最小に制限する必要があります。

于 2009-03-28T15:59:00.527 に答える