2012-04-15 11 views
4

ich einen Compiler und Link Problem in meinem Programm zu untersuchen, wenn ich auf das folgende Makro kam, die in einem Header und Quelldatei definiert wurde:Warum erscheint mein #define-Makro global?

/* file_A.c */ 
#ifndef _NVSize  
    #define _NVSize 1 
#endif 

/* file_B.c */ 
#include "My_Header.h" 
#ifndef _NVSize  
    #define _NVSize 1 
#endif 

/* My_Header.h */ 
#define _NVSize 1024 

nichts aus dem Üblichen noch, bis ich die folgenden Informationen sah in der GCC-Ausgabe map-Datei:

/* My Map File */ 
... 
.rodata 0x08015694 _NVSize 
... 

Mein Verständnis der map-Datei ist, dass, wenn Sie ein Symbol in dem .rodata Abschnitt der map-Datei, dieses Symbol zu sehen ist, als globaler Variable vom Compiler behandelt wird. Dies sollte jedoch nicht der Fall sein, da Makros vom Präprozessor behandelt werden sollten, bevor der Compiler die Datei analysiert. Dieses Makro sollte vor dem Kompilieren durch seinen definierten Wert ersetzt werden.

Ist dies die Standardmethode, mit der GCC Makros behandelt, oder gibt es einen implementierungsspezifischen Grund, dass GCC dies als global behandelt (Debug-Einstellung vielleicht)? Was bedeutet das auch, wenn mein Makro in einer anderen Quelldatei neu definiert wird? Habe ich es einfach für eine einzelne Quelldatei neu definiert oder habe ich eine globale Variable geändert, wodurch _NVSize überall in meinem Programm geändert wurde?

+0

Tritt dies auch beim Kompilieren mit Optimierungen/ohne Debugging auf? – delnan

+0

Die Compilereinstellungen für die Datei sind -O1 -MD -ggdb ... –

+0

Ich sehe keine Linker-Einstellungen in der Build-Ausgabe, ich werde dies ausgraben müssen. –

Antwort

3

Ich denke, der Compiler ist frei, Ihr Makro zu einer globalen Variablen zuzuweisen, solange sichergestellt wird, dass dies das exakt gleiche Ergebnis erzeugt, als ob es einen textuellen Ersatz getan hätte.

die Erstellung Während der Compiler dies speziell global markieren zu bezeichnen, dass es ein Makro konstanter Wert ist, so dass keine erneute Zuordnung möglich ist, kann keine Adresse genommen werden usw.

Wenn Sie das Makro neu definieren in Ihr Sorge, der Compiler führt diese Transformation möglicherweise nicht durch (und behandelt sie wie erwartet: ein Textersatz vor Kompilierung), führen Sie sie auf einem der verschiedenen Werte aus (oder sagen Sie, dass für jedes Vorkommen unterschiedliche Namen verwendet werden)) oder tun etwas anderes :)

+0

Ich muss dies testen, um zu sehen, welche Werte tatsächlich in file_A und file_B verwendet werden. Aber wenn Sie sich den Beispielcode ansehen, sollte _NVSize SOLL 1 für Datei_A sein, und _NVSize SOLL 1024 für Datei_B sein - Stimmen Sie zu? –

+0

@ BryanC.- Ja, das ist es, was der Standard erfordert (aus der Sicht des Codes). Beachten Sie jedoch, dass es letztlich darauf ankommt, ob das Programm während der Ausführung das gewünschte (dh standardmandatierte) Ergebnis erzeugt oder nicht, was davon abhängt, wie Ihr Compiler den _NVSize-Wert verwendet. – Attila

+0

"Ich denke, der Compiler kann Ihr Makro frei zuweisen globale Variable "Irgendwelche Zitate dafür? Cos Ich bin sehr neugierig zu wissen, wie das Makro der Pre-Prozessor-Ersatz entkam? –

1

Makros werden im Präprozessorschritt ersetzt, der Compiler sieht nur das ersetzte Ergebnis. Wenn also der Makroname angezeigt wird, dann ist meine Wette, dass das Makro nicht am Verwendungsort definiert wurde. Es ist zwischen den spezifischen #define _NVSize und einem #undef _NVSize definiert. Die Neudefinition eines vorhandenen Makros ohne Verwendung einer #undef sollte zuerst zu einem Präprozessorfehler AFAIR führen.

BTW, sollten Sie Ihre Makronamen nicht mit einem Unterstrich beginnen. Diese sind für die Implementierung reserviert.

+0

Redefinition führt zu "Stapeln" der Werte. Der alte Wert kann durch ein '# undef 'neu installiert werden. Eine Neudefinition kann (sollte?) Jedoch eine Warnung ausgeben. – wildplasser

+1

Huh? Ich weiß nicht, über welche Sprache oder welche C-Erweiterung du sprichst, aber Standard C erlaubt keine Stapelung von Definitionen. Ein existierendes Makro kann neu definiert werden, wenn beide Definitionen gleich sind, z. erlauben, das gleiche Makro in verschiedenen Header-Dateien zu definieren. Siehe 6.10.3.2 im Standard. – Secure

+0

Sie haben Recht. Ich muss von einem Compiler verwirrt gewesen sein, den ich vor Jahren benutzt habe. Ich habe den Mechanismus sowieso nie benutzt. zu gefährlich. – wildplasser