2013-08-09 13 views
6

Ich kann nicht verstehen, warum das nicht funktioniert.Reihenfolge der `statischen` Definition und` externen Deklaration` in einer Übersetzungseinheit

extern int i; 

int main() 
{ 
    printf(" %d ", i); 
} 

static int i =3; 

Auch das funktioniert nicht:

extern int i; 

static int i =3; 

int main() 
{ 
    printf(" %d ", i); 
} 

Aber wenn static Variable vor dem extern declaration definiert ist es funktioniert:

static int i =3; 

extern int i; 

int main() 
{ 
    printf(" %d ", i); 
} 

Wie ich aus extern int i verstehen erzählt, dass i ist Geschenk woanders und hier, wie es aussieht (int i)

Aber woanders Mittel:

1) Vielleicht, später in der same Übersetzungseinheit als global variable.

2) Vielleicht in einigen other Translationseinheit.

Ich dachte, dass (1) würde gültig sein, obwohl static int i = 3 hat Umfang i auf die aktuelle Übersetzungseinheit eingeschränkt, wo es definiert ist.

Ist nicht static int i =3global (ich meine zumindest atleast ist es in der Übersetzungseinheit sichtbar) hier, obwohl es den eingeschränkten Umfang zu seiner Übersetzungseinheit hat? Warum kann der Compiler das nicht finden?

Wenn ich kompilieren die ersten beiden Versionen ich die folgende Kompilierung Fehler:

error: static declaration of ‘i’ follows non-static declaration 
note: previous declaration of ‘i’ was here 

Ich kann diese Fehlermeldung verstehen. Auch warum beschwert es sich als eine statische declaration ist es nicht ein definition auch?

+0

Was genau "funktioniert nicht"? Ist es ein Kompilierungsproblem? Laufzeitproblem? Ich kompiliere Ihren Code mit VS 2010 und es scheint ordnungsgemäß zu funktionieren. – Nbr44

+0

GCC comipler, ich bekomme eine Kompilierzeit Fehler statische Deklaration von ich folgt nicht-statische Deklaration. –

Antwort

6

C11 6.2.2 Linkages von Identifikatoren Abschnitt 4

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

So ist die zweite Erklärung die erste folgen, zurück auf Ihre Beispiele, die 1. und 2. Beispiel i wird eine extern Speicherklasse haben. Der Compiler denkt, dass das ein Fehler ist.

Während im dritten Beispiel wird istatic sein, weil static zuerst angezeigt wird. Das sollte kein Problem sein.

Und in Abschnitt 7 von C11 6.2.2 Linkages von Identifikatoren

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

Also ist es besser, nicht die gleiche Variable mit beiden static und extern in derselben Übersetzungseinheit zu erklären.

+0

Ja, ich stimme zu. Was mich aber immer noch beunruhigt, ist, warum die '3'te Version' immer' funktioniert? Über viele Compiler hinweg. –

+0

@UchiaItachi: Warum sorgen Sie sich um die dritte Version? Diese Antwort zitiert Text aus dem C-Standard, der es erklärt: Wenn eine "extern" -Deklaration einer Deklaration mit interner ("statischer") oder externer Verknüpfung folgt, wird die vorherige Deklaration verwendet. –

+0

@UchiaItachi Für eine Sache, selbst wenn Sie alle Compiler getestet haben, die Sie eindeutig nicht können, und es alles funktioniert, bedeutet das nicht, dass es definiertes Verhalten ist. Der Standard ist der zu entscheiden. –

2

Nun, eine Variable ist entweder extern oder static. Denken Sie daran, dass static auf globaler Ebene seine Sichtbarkeit nur auf die aktuelle Übersetzungseinheit beschränkt, während extern vorschreibt, dass es über verschiedene Übersetzungseinheiten hinweg sichtbar ist.

+0

Ich weiß, dass "statisch" die Sichtbarkeit und "extern" über andere Übersetzungseinheiten "einschließlich" der aktuellen übersetzen kann. Aber der Code funktioniert, wenn ich die statische Variable vorher definiere und eine externe Erklärung gebe, die beweist, dass sie "statisch" und "extern" hat. –

+0

Das hat mich tatsächlich wirklich ratlos gemacht, aber meine einzige Erklärung ist die Fehlermeldung selbst: 'statische Deklaration von 'i' folgt nichtstatischer Deklaration '. Wie ich es verstehe, muss "statisch" jeder nicht statischen Deklaration vorausgehen. Und wenn "extern" erreicht ist, gibt es bereits eine Definition von "i", mit der "extern" glücklich ist. – Nobilis

0

Es macht keinen Sinn, etwas als static und wieder als extern zu deklarieren. Dies ist ein undefiniertes Verhalten, also tun Sie es nicht.

+0

Aber warum gibt es nicht die Erklärung von "extern"? Um zu sagen, dass es weiter unten in der Datei definiert ist? Und ich weiß, dass Ihr Code funktioniert, wie ich bereits in meiner Frage erwähnt habe. –

+0

@UchiaItachi, meine Antwort bearbeitet, ist es jetzt korrekt. Es ist undefiniertes Verhalten. –

Verwandte Themen