2016-03-21 7 views
1

私はなぜ、次の作品のように混乱しています:Cで変数のexternが省略されていますが、それでも動作しますか?

test.cの

#include <stdio.h> 

int g; 
// ??? should be extern int g; ??? 

int main(){ 
    printf("%i\n", g); 
    return 0; 
} 

lib.c

int g = 3;

私は、コンパイル時に重複したシンボルエラーを取得していないのですなぜ?私はこれをC++でやろうとしている間にエラーが出るので、私を満足させます。しかし、この例では、externを含めるかどうかにかかわらず、すべてがコンパイルされて動作します(つまり、3が正常に印刷されます)。 Cのexternに関するStackOverflowに関する他の質問をすべて読むと、変数に使用されているexternが変数を宣言しているが、その変数を定義していない(つまりメモリを割り当てている)と誰も言わないようです。しかし、ここでexternを使用しないと、gと呼ばれる2つの別々の変数を定義しているので、何らかの重複シンボルエラーが発生するはずです。しかし、そうではないので、私は非常に混乱しています。

+0

をあなたは 'lib.cを含めていない。その結果、「test.cの」中gは、その値が3

に初期化されても参照してください「lib.c」でgを指し、 '? – Carcigenicate

+0

どのようにコンパイル/リンクしますか? –

+0

これは奇妙なC(C++ではない)のものです。こちらをご覧ください:http://stackoverflow.com/questions/3095861/about-tentative-definition、またはこちら:http://ninjalj.blogspot.ch/2011/10/tentative-definitions-in-c.html –

答えて

1

N1570、6.9.2(強調鉱山):

2イニシャライザことなく、ストレージ・クラス指定なし又は とスコープファイル持つオブジェクトに対する識別子の宣言ストレージクラス指定子staticは、暫定的な の定義を構成します。

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 

あなたの "test.cの" にint g;は(実施例参照)g外部リンケージを与え、仮定義です。しかし、 "lib.c"内のint g = 3;には初期化子があるので、仮定義ではありません。 http://en.cppreference.com/w/c/language/extern

関連する問題