2016-03-21 8 views
1

Ich bin wie, warum die folgenden Werke verwirrt:Weglassen von extern für Variable in C, aber funktioniert immer noch?

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;

Warum bin ich nicht ein Duplikat Symbolfehler beim Übersetzen zu bekommen? Ich bekomme den Fehler beim Versuch, dies in C++ zu tun, damit mich das befriedigt. In diesem Beispiel kompiliert und arbeitet alles (d. H. Druckt 3 erfolgreich), ob oder ob nicht extern enthalten ist. Beim Lesen aller anderen Fragen zu StackOverflow über extern in C scheint jeder zu sagen, dass external, das für eine Variable verwendet wird, die Variable deklariert, aber nicht definiert (d. H. Speicher reserviert). Aber hier, wenn ich extern nicht verwende, dann definiere ich zwei separate Variablen, die beide g genannt werden, also sollte es eine Art von doppeltem Symbolfehler geben. Aber da ist es nicht, also bin ich sehr verwirrt.

+0

Sie sind nicht inklusive 'lib.c '? – Carcigenicate

+0

Wie kompilieren/verknüpfen Sie es? –

+0

Es ist seltsam C (aber nicht C++) Zeug. Schau mal hier: http://stackoverflow.com/questions/3095861/about-centative-definition, oder hier: http://ninjalj.blogspot.ch/2011/10/tentative-definitions-in-c.html –

Antwort

1

N1570, 6.9.2 (Emphasis mir):

2 Eine Erklärung eines Bezeichners für ein Objekt, das Umfang hat ohne Initialisierer und ohne Speicherklasse Spezifizierer oder mit Datei Der Speicherklassenspezifikator static stellt eine vorläufige Definition dar.

4 Beispiel 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 

Die int g; in Ihrem "test.c" ist eine vorläufige Definition, g externe Bindung zu geben (siehe Beispiele). Jedoch hat int g = 3; in "lib.c" einen Initialisierer, also ist es keine vorläufige Definition. Als Ergebnis bezieht sich der g in "test.c" der g in "lib.c", dessen Wert initialisiert 3.

Siehe auch: http://en.cppreference.com/w/c/language/extern