2016-10-16 19 views
2

Cでこのコードが許可されているのはなぜですか?Cで許されるグローバル変数の再宣言?

int x; 

int main() { 
    printf("%d\n", x); 
    return 0; 
} 

int x = 2; 

それはgccclangの両方で-Wall -std=c89を使用して警告なしでコンパイルされます。

グローバルスコープのint xは、int x = 0に相当すると以前考えました。私は驚いている。

+0

@ pablo1977 'x' **は静的変数です! – Olaf

答えて

1

int x;を禁止され、ファイルスコープで、同様@PSkocikで答えて初期化と定義が存在しない場合はint x = 0;のように動作します仮定義です。

グローバルスコープのint xは、int x = 0に相当すると以前考えました。

約トリッキーな部分「グローバル」int x;は、それが別のint x = constant;任意コンパイル単位に存在しない場合は、0で初期化されている0で初期化されると仮定されます。

したがって、オブジェクトを初期化する必要がある場合は、明示的な初期化を推奨し、デフォルトの初期化を0ビットにはカウントしないことをお勧めします。

// Does an initialization exist, in some file -maybe? 
int x; 
// Better. If another file initializes `x`, good to see a compiler/linker error. 
int x = 0; 
+0

私はこれが完全に正しいとは思わない。 1つのTUに1つの暫定的な定義を持ち、もう1つに初期化子を持つものは、標準でカバーされていません。これらは2つの反対の定義であり、したがってUBにつながります。 gccは拡張機能としてこれを行いますが、他のコンパイラではそうではありません。 –

+0

@JensGustedtおそらくそう。レビューされます。 – chux

-2
int x; 

宣言です。

int x = 2; 

定義(宣言でもあります)です。

宣言が互換性がある限り(同じ)、再宣言は許可されます。

int x; 
int x; 

となります。再定義できません。

int x = 2; 
int x = 2; 

動作しません。その前または定義せずに宣言せずに
使用は

+2

'int x;'はfile-scopeで_tentativeの定義です。そして 'int x = 2;'も宣言です。 – Olaf

+0

@Olaf、そうですが、実際の定義がある限り、暫定的な定義は無関係です。名前が言うように、他のものが来ない限り、暫定的です。 –

+0

外部リンケージを持つ名前には、常にヘッダファイル内で最適な「extern」宣言がある必要があります。それ以外の場合は内部リンケージを使用します。 – Olaf

関連する問題