Es gibt zwei Quelldateien in meinem Programm.
Ein Array ist in A.cpp definiert.
%Vor%Es wird in B.cpp verwendet.
%Vor%AFAIK, Linker löst einen Fehler aus, wenn keine übereinstimmende Definition für eine Deklaration gefunden werden kann, wenn der deklarierte Bezeichner verwendet wird. Hier sind offensichtlich int [] und int [100] zwei verschiedene Typen.
Warum gibt es in diesem Fall keinen Verbindungsfehler? Ist durch der Standard sichergestellt, dass die Array-Größe während des Abgleichs von Deklaration / Definition trivial ist? Oder es ist nur umsetzungsspezifisch? Ein Zitat von dem Standard wird geschätzt, falls vorhanden.
Edit: iammilind erwähnt in seiner Antwort, dass Linker richtig laufen kann (sein Compiler ist gcc) , auch wenn der Typ NICHT zwischen Deklaration und Definition übereinstimmt. Ist es durch den Standard oder nur ein Weg von gcc erforderlich? Ich denke, das ist ein viel wichtigeres Problem, um herauszufinden.
In C und C ++ entspricht eine Deklaration eines Objekts a
des unvollständigen Typs der Definition des Objekts a
, bei der der Typ vollständig ist. Was Sie beobachten, veranschaulicht einfach die Tatsache, dass Sie in C ++ in nicht definierenden Deklarationen unvollständige Typen verwenden dürfen. Aber sobald Sie zu der Definition kommen, muss der Typ abgeschlossen sein.
Dieses Verhalten ist nicht auf Arrays beschränkt. Zum Beispiel können Sie
deklarieren %Vor% für eine völlig unbekannte Klasse X
, und wenn class X
bereits vollständig definiert ist, können Sie
, das mit der obigen Deklaration übereinstimmt.
Das Gleiche passiert mit Ihrem Array. Zuerst deklarieren Sie ein Objekt des unvollständigen Typs
%Vor%und dann definieren Sie es mit vollständigem Typ
%Vor%Die Typen stimmen hier nicht überein. Die C ++ - Sprache erforderte jedoch keine Übereinstimmung mit ihnen. Zum Beispiel gibt 3.9 / 7 explizit
anDer deklarierte Typ eines Array-Objekts könnte ein Array unbekannter Größe sein und deshalb an einer Stelle in einer Übersetzungseinheit unvollständig sein und später vervollständigen; die Array - Typen an diesen beiden Punkten ("Array of unbekannte Grenze von T "und" Array von N T ") sind verschiedene Arten.
Dies bedeutet, dass dasselbe -Arrayobjekt anfänglich unvollständig sein kann, aber später einen vollständigen Typ annimmt. (Siehe auch das Beispiel in 3.9 / 7). Dies bedeutet natürlich nicht, dass Sie a
als int
deklarieren und dann als double
definieren können. Die einzige typbezogene Freiheit, die Sie hier haben, ist wiederum, einen unvollständigen Typ zu vervollständigen. Nicht mehr.
Zunächst sollte dieser Code keinen Fehler geben. Die Angabe int a[]
unterscheidet sich von a[100]
, ist aber damit kompatibel (sie ist nur unvollständig).
Ein zweiter wichtiger Punkt ist, dass Sie sich nicht darauf verlassen können, dass der C ++ - Compiler / -Linker Fehler für die modulübergreifende Inkohärenz liefert. Zum Beispiel kann man in einem C ++ - Programm nicht dieselbe Klasse zweimal mit einer anderen Definition definieren, aber der Compiler ist NICHT ERFORDERLICH, um Sie über dieses Problem zu informieren, es ist eine Belastung für die Programmierer.
Wenn eine Implementierung diese Art von Problem erkennt und signalisiert, dann ist das in Ordnung, aber eine Implementierung, die nichts darüber aussagt und nur abstürzende ausführbare Dateien erstellt, ist immer noch vollkommen kompatibel.
Hier steht, dass "C ++ die Möglichkeit erlaubt, die eckigen Klammern leer zu lassen []. In diesem Fall wird der Compiler eine Größe für das Array annehmen, die der Anzahl der Werte entspricht, die zwischen geschweiften Klammern {}" enthalten sind. Wenn dieser Verweis richtig ist, scheint es Teil des Standards zu sein.
Ihre Frage ist echt. Hier gibt es einige Probleme.
Wenn Sie zwei Symbole mit demselben Namen deklarieren; dann gibt es keine Überprüfung
von Linker für seinen Typ / Größe etc. Es löst sie nur und
korrelieren sie zusammen. Versuchen Sie zum Beispiel, extern float
a[];
oder extern int a[3];
zu deklarieren. So ist C ++
Linker ist (leider) entworfen.
Die Lösung besteht also darin, sie sowohl in a.cpp als auch in b.cpp in der Header-Datei und #include
zu deklarieren.