デフォルトでは、グローバル変数には外部リンケージがあります。これは、他のソースファイル(または「変換ユニット」)で使用できることを意味します。static
代わりに、キーワードを使用してグローバル変数を宣言すると、それらは内部リンケージを持ちます。つまり、他のソースファイルでは使用できなくなります。
外部リンケージを持つ変数の場合、同じ名前の変数を複数持つことはできません。そうしないと、リンカが文句を言います。ただし、少なくとも1つに内部リンクがある限り、同じ名前の2つの変数を持つことができます。もちろん、同じソースファイルで両方を参照することはできません。
extern
宣言は、コンパイラに「別の変換ユニットで定義された外部リンケージを持つ変数の名前です」と言っているだけで、その変数を参照できます。
名前空間が追加されていることを除けば、C++はまったく同じです。グローバル変数が名前空間内に配置されている場合、それらが異なる名前空間にある場合、リンカーエラーなしで同じ名前を持つことができます。もちろん、これらの変数へのすべての参照は、フルネームを参照するかnamespace::var_name
、宣言を使用しusing
てローカル名前空間コンテキストを確立する必要があります。
C ++には匿名の名前空間もあります。これはstatic
、Cでグローバル変数にキーワードを使用するのとまったく同じです。匿名の名前空間内で宣言されたすべての変数と関数には内部リンクがあります。
したがって、元の質問に答えるのは正しいです。コンパイルは成功しますがx
、外部リンケージ(具体的には、変換単位one.c
とtwo.c
)を使用した変数の定義が複数あるため、リンクは失敗します。
からthree.c
、両方の変数を同時に参照する方法はありませんx
。一方または両方のモジュールで名前を変更するか、C++に切り替えて名前空間内x
に少なくとも1つ配置する必要があります。x