2010-03-27 12 views
5

Was ist der Unterschied zwischen den folgenden zwei Deklarationen? Ich dachte, sie wären gleichwertig, aber die erste Probe funktioniert, und die zweite nicht. Ich meine, es kompiliert und läuft, aber der Bitmap-Display-Code zeigt leer. Ich bin noch nicht durchgetreten, aber vermisse ich etwas Offensichtliches? GUI_BITMAP ist eine einfache Struktur, die eine Bitmap beschreibt. Dies ist für VC++ 2005, aber ich denke, es schlägt auch in VC++ 2008 fehl. Verkratzen meinen Kopf auf dieses ...Problem mit extern keyword in C++

Probe 1:

extern "C" const GUI_BITMAP bmkeyA_cap_active; 
extern "C" const GUI_BITMAP bmkeyA_cap_inactive; 

Probe 2:

extern "C" 
{ 
    const GUI_BITMAP bmkeyA_cap_active; 
    const GUI_BITMAP bmkeyA_cap_inactive; 
}; 

Edit: Weitere Erkundungen hat gezeigt, dass das zweite Beispiel die Strukturen schafft, während die erste sich auf externe Strukturen bezieht. Das zweite Beispiel sollte nicht gelinkt werden, da es zwei globale Variablen mit demselben Namen gibt. Aber es tut es nicht, es sendet eine zero gefüllte Struktur an den Display-Code, der aufgibt. Hmmm .....

Bearbeiten 2: Ausführen des gleichen Codes durch einen anderen Compiler (IAR) tatsächlich fehlgeschlagen, um auf Sample 2 zu kompilieren, mit einem Fehler über das Fehlen eines Standardkonstruktors. Ich vermute also, dass etwas Subtiles über das Schlüsselwort "extern", Strukturen und C++, das ich nicht bekomme, etwas ist. Wenn die Dinge im externen Bereich Funktionen wären, wären die beiden Samples identisch, oder?

Antwort

3

Ihr Linker kann die doppelten Symbole hinter Ihrem Rücken still lösen. Sie können statische Bibliotheken von einem Anbieter erhalten und diese mit Ihrem Programm verknüpfen. Was ist die Lösung für die Situation, in der Sie zwei solcher Bibliotheken haben und beide ein gemeinsames Symbol definieren? Der Linker wird das nur auflösen, indem er die eine oder andere Definition auswählt und Sie mit dem Fallout beschäftigt. Wie gehen Sie mit der Link-Phase Ihrer Bewerbung um? Sie können bessere Ergebnisse erzielen, wenn Sie .o-Dateien direkt verknüpfen, anstatt sie in Zwischenbibliotheken zu stellen, bevor Sie die endgültige Anwendung verknüpfen.

This page der ARM-Dokumentation beschreibt das Problem gut - ich erwarte ein ähnliches Verhalten in Ihrem Fall passiert:

Mehrere Definitionen eines Symbols in verschiedenen Bibliotheksobjekte sind nicht unbedingt erkannt. Sobald der Linker eine geeignete Definition für ein Symbol gefunden hat, hört er auf, nach anderen zu suchen. Unter der Annahme, dass das Objekt, das das Duplikatsymbol enthält, aus anderen Gründen nicht geladen wird, tritt kein Fehler auf. Dies ist beabsichtigt und in einigen Situationen besonders nützlich.

Edit: Weitere Suche hat aufgedreht, dass dieses Problem wegen einer Verletzung der „One Definition Rule“ verursacht wird, und als Ergebnis wird der Compiler/Linker ist nicht erforderlich, um Sie über das Problem zu informieren. Das macht Ihre Frage zu einem Duplikat von this one.

+0

Danke für die Antwort, aber hier sind keine Bibliotheksobjekte im Einsatz, das ist alles nur mein Code, eine Mischung aus C und C++. Meine ursprüngliche Frage bleibt - was ist der Unterschied zwischen Beispiel 1 und Beispiel 2 - Ich dachte, sie sollten genau den gleichen Code generieren? Wenn die Dinge Funktionen statt Strukturen wären - sie sind das Gleiche, oder? – Jeff

+1

@Jeff, die schnelle Antwort auf Ihre Frage ist, dass nein, diese beiden sind nicht das Gleiche, weshalb Sie Probleme sehen.Im zweiten Fall ändern Sie nur die Anweisungen in '{}', um die Verknüpfungskonventionen von C zu verwenden. Im ersten Beispiel tun Sie das * plus *, was darauf hinweist, dass die Variablen an anderer Stelle deklariert sind. http://msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx –

0

Das zweite Beispiel könnte dem ersten mit einem extra extern vor dem const entsprechen. Im ersten Fall kombiniert der Compiler wahrscheinlich die beiden Verwendungen von extern. Im zweiten Fall würde ich annehmen, dass der Compiler aus irgendeinem Grund nicht alles im externen Umfang extern ist.