Sollte die Variablendefinition in Header-Dateien enthalten sein?

Lesezeit: 3 Minuten

Benutzer-Avatar
Methoden

Meine sehr grundlegenden Kenntnisse von C und Kompilierungsprozess ist in letzter Zeit eingerostet. Ich habe versucht, eine Antwort auf die folgende Frage zu finden, aber ich konnte die Grundlagen der Kompilierungs-, Verknüpfungs- und Vorverarbeitungsphase nicht verbinden. Auch eine kurze Suche bei Google hat nicht viel geholfen. Also beschloss ich, zur ultimativen Quelle des Wissens zu kommen 🙂

Ich weiss: Variablen sollten nicht in den .h-Dateien definiert werden. Es ist in Ordnung, sie dort zu deklarieren.

Warum: Weil eine Header-Datei möglicherweise von mehreren Stellen eingebunden wird, wodurch die Variable mehr als einmal neu definiert wird (Linker gibt den Fehler aus).

Mögliche Problemumgehung: Verwenden Sie Header-Guards in Header-Dateien und definieren Sie darin Variablen.

Ist es wirklich eine Lösung: Nein. Weil Header-Guards für die Vorverarbeitungsphase sind. Das heißt, dem Compiler mitzuteilen, dass dieser Teil bereits enthalten ist, und ihn nicht noch einmal einzufügen. Aber unser mehrfacher Definitionsfehler kommt im Linker-Teil – viel nach der Kompilierung.

Diese ganze Sache hat mich verwirrt darüber, wie Vorverarbeitung und Verknüpfung funktionieren. Ich dachte, dass die Vorverarbeitung den Code einfach nicht enthalten wird, wenn das Header-Guard-Symbol definiert wurde. Sollte in diesem Fall nicht auch die Mehrfachdefinition eines Variablenproblems gelöst werden?

Was passiert, dass diese Vorverarbeitungsdirektiven den Kompilierungsprozess davor bewahren, Symbole unter Header Guards neu zu definieren, aber der Linker immer noch mehrere Definitionen des Symbols erhält?

Eine Sache, die ich in der Vergangenheit verwendet habe (als globale Variablen in Mode waren):

var.h-Datei:

...
#ifdef DEFINE_GLOBALS
#define EXTERN
#else
#define EXTERN extern
#endif
EXTERN int global1;
EXTERN int global2;
...

Dann in eines .c-Datei (normalerweise diejenige, die main() enthält):

#define DEFINE_GLOBALS
#include "var.h"

Der Rest der Quelldateien enthält normalerweise nur “var.h”.

Beachten Sie, dass DEFINE_GLOBALS kein Header-Wächter ist, sondern das Deklarieren/Definieren der Variablen ermöglicht, je nachdem, ob sie definiert sind. Diese Technik ermöglicht eine Kopie der Deklarationen/Definitionen.

Header Guard schützt Sie vor mehreren Einschlüssen in einer einzigen Quelldatei, nicht vor mehreren Quelldateien. Ich denke, Ihr Problem rührt daher, dass Sie dieses Konzept nicht verstehen.

Es ist nicht so, dass Präprozessorwächter während der Kompilierzeit vor diesem Problem sparen. Tatsächlich wird während der Kompilierzeit nur eine Quelldatei in ein Objekt kompiliert, Symboldefinitionen werden nicht aufgelöst. Aber im Falle einer Verknüpfung, wenn der Linker versucht, die Symboldefinitionen aufzulösen, wird er verwirrt, wenn er mehr als eine Definition sieht, was dazu führt, dass er den Fehler kennzeichnet.

Sie haben zwei .c-Dateien. Sie werden zusammengestellt separat. Jeder enthält Ihre Header-Datei. Einmal. Jeder bekommt eine Definition. Sie stehen zur Verbindungszeit in Konflikt.

Die herkömmliche Lösung lautet:

#ifdef DEFINE_SOMETHING
int something = 0;
#endif

Dann #define DEFINE_SOMETHING in einziger .c-Datei.

  • Eine bessere Lösung ist eine Deklaration im Header und eine Definition in nur einer .c-Datei.

    – William Pursel

    7. Februar 2010 um 17:03 Uhr

Header Guards verhindern, dass eine Header-Datei mehrfach eingebunden wird in derselben Übersetzungseinheit (dh in der gleichen .c-Quelldatei). Sie haben keine Auswirkung, wenn Sie die Datei in zwei oder mehr Übersetzungseinheiten einschließen.

1365920cookie-checkSollte die Variablendefinition in Header-Dateien enthalten sein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy