Ich habe eine Frage zum folgendem Präprozessoranweisungen: #ifndef _COM_H_ #define _COM_H_ Code #endif Was wird den hier gemacht? Also falls ein com.h nicht defeniert ist, dann wird esdefiniert und der code zwischen define und endif ausgeführt. Aber wenn die Datei nicht com.h heißt, dann findet er diese sowieso nicht. Kann mir jemand erklären wie sich der Pärprozessor verhält? Vielen Dank im Voraus.
Das ist ein Schutz gegen Mehrfach-Inkludierungen. Nur wenn der Header "com.h" noch nicht eingebunden ist wird das define bekannt gemacht und der Header inkludiert. Ansonsten ist das define bereits bekannt und der Header wird nicht nochmal inkludiert. Vorteile sind ein schnellerer Präprozessor und übersichtliche *.i Files (Dateien in denen defines und Makros bereits ersetzt sind. Braucht man manchmal wenn der Code durch Präprozessorverzweigungen unübersichtlich wird.)
Die Makros sorgen dafür das ein header nur einmal included wird. Stell dir vor du hast eine main.c die so anfängt. #include <wurst.h> #include <com.h> in der wurst.h hast du jetzt aber #include <stdlib.h> #include <com.h> Ohne das ifdef Konstrukt von oben würde com.h zwei mal eingesetzt werden. Der C-Präprozessor ist sehr stumpfsinnig wenn es um include geht.
Hiermit wird verhindert, dass "Code" mehrfach eingefügt wird. Mit einer Datei com.h hat dies zunächst nichts zu tun.
Hallo Du schmeißt da was durcheinander. COM_H hat erstmal garnichts mit com.h zu tun. Vielleicht meinst du sowas: #ifndef COM_H #define COM_H #include <com.h> #endif Das kannst du verwenden um zu verhindern, das com.h mehrmals "included" wird. Gruß Joachim
> Was wird den hier gemacht? Die Anweisungen stammen mit sehr hoher Wahrscheinlichkeit aus einer Header-Datei. Header-Dateien können mehrfach in verschiedenen Modulen mittels include eingebunden werden. Mehrfach-Einbindungen sind aber sinnlos und erzeugen teilweise auch Fehler/Warnungen (Redefinitions usw.), außerdem wäre es ja auch doppelter Code. Mit der obigen Anweisung wird also nur unnötiger/doppelter Code vermieden. > Aber wenn die Datei nicht com.h heißt, dann findet er diese sowieso > nicht. Verstehe ich nicht. COM_H ist ein frei gewähltes define, welches allerdings unbedingt zu einer com.h-Header-Datei gehören sollte, allein schon, damit der Code halbwegs verständlich wird. ;-) Also, es muss nicht zu einer com.h gehören, sollte aber, damit es verständlich ist. > Kann mir jemand erklären wie sich der Pärprozessor verhält? Hast du doch schon selbst getan.
Vielen Dank für die Erklärungen. Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen zusammengefasst sind. In jedem meinem c-File mache includiere ich einfach nur defeines.h also #include "defines.h" In jedem .h files mache ich folgendes: #ifndef COM_H #define COM_H Code #endif Die Aussage von Joachim verwirrt mich ein wenig muss ich das so machen: #ifndef COM_H #define COM_H #include <com.h> #endif Vielen Dank.
Wenn die Header-Datei "tralalabums.h" heißt, dann: #ifndef TRALALABUMS_H Wenn die Header-Datei "gagga_banana.h" heißt, dann: #ifndef GAGGA_BANANA_H Zum Beispiel.
SeriK schrieb: > Die Aussage von Joachim verwirrt mich ein wenig muss Du musst gar nichts. > ich das so machen: > > #ifndef COM_H > #define COM_H > > #include <com.h> > > #endif Mach das nicht so. Der "Include-Guard" (so nennt man eine derartige Sequenz) sollte in die Header Datei. Hauptzweck eines Include Guards ist es nicht die Compile-Zeit zu verringern, sondern doppelte Deklarationen bzw. Redefines zu verhindern. Nico Erfurth hat weiter oben ja schon gezeigt, wie so etwas entstehen kann. > Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen > zusammengefasst sind. Für ein µC-Projekt, welche traditionell eher klein sind, mag so ein Rundumschlag angehen. Aber eigentlich ist das der falsche Weg. Jedes *.c includiert nur diejenigen *.h die sie tatsächlich benötigt. Benötigt ein *.h File wieder ein anderes *.h, so includiert dieses *.h File seinerseits dasjenige *.h welches es benötigt. Nur so bekommt man eine minimale Make-Hierarchie, bei der make dann auch nur tatsächlich diejenigen Teile nachcompiliert, die direkt oder indirekt von einem geändertem Header-File abhängen. Wie gesagt, bei kleinen µC-Projekten mit Komplett-Build-Zeiten von 1 oder 2 Minuten oder weniger, spielt das untergeordnete Rolle. Wenn der Unterschied zwischen einem Komplett-Build und einem Teilbuild allerdings in den Bereich Stunden versus Minuten geht, dann macht das einen Unterschied.
> Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen > zusammengefasst sind. Warum? defines.h sind oft sinnvoll, aber nicht zum inkludieren von allen Headern, sondern für global/projektweit genutzte Defines. > In jedem meinem c-File mache includiere ich einfach nur defeines.h > also #include "defines.h" Das wird nur unübersichtlich werden, in der jeweiligen c-Datei bindet man nur die wirklich benötigten Header ein. > In jedem .h files mache ich folgendes: Dem Schema solltest du folgen, aber nicht immer COM_H nehmen. Für test.h nimmst du TEST_H Für blah.h nimmst du BLAH_H denn du brauchst für jeden Header einen eigenes Define und um der Lesbarkeit Willen, leitest du dass einfach vom Header-Namen ab. Das musst du aber nur bei selbst erstellten Header-Dateien machen! > Die Aussage von Joachim verwirrt mich ein wenig muss ich das so machen: Mich auch, denn ifdef usw nimmt man im Normalfall im Header. P.S.: Du brauchst ein gutes C-Buch oder Tutorial, dass sind Grundlagen, die du dir einfach selbst erarbeiten musst.
> Also ich habe ein defines.h - File, wo alle meine eigene .h dateinen > zusammengefasst sind. Das ist aber nicht gerade sinnvoll. Bei größeren Projekten wird das ganze sehr langsam.
Diese konstrukt nennt man auch Codeguard oder IncludeGuards. Sollte eigentlich in jede H.Datei rein. (wers nicht macht, handelt sich nur probleme ein, oder er weiss genau was er macht) sie sollen verhindern, das Header Files mehrach in einer übersetzungseinheit (c.Datei) eingebunden werden. der Compiler hat normalerweise danach seine kleineren bis grösseren probleme, wenn der Inhalt der H.Dateien mehrfach in der übersetzungseinheit vorkommt. Redefinition fehler / Warnungen, ... auserdem kann es bei hässlichen include construktionen dazu führen, das man include schleifen baut. (z.B. durch gegenseitiges includieren über 5 Ecken) was dazu führen kann, das der code sich so erst gar nicht übersetzen lässt. normalerweise mekert der compiler mit irgend einer abstrakten fehlermeldung von wegen include und schleifen und so, oder schmirt ganz einfach nur weg, weil im der speicher aus geht. Ein Präprozessor ist eigentlich ein Dummes programm, er ersetzt nur alle angegebenen #defines #includes durch die angegebenen inhalte. beim inlcude halt durch den inhalt der angegebenen Datei. Dadurch kann man oft benötigte Definitonen, und Declarationen (Funktionen, Globale Variablen) in einer separaten Datei pflegen. Und muss sie nicht in jeder Übersetzungseihneit separat einpflegen (wartungsaufwendig und fehleranfällig)
nochwas es gibt bei manchen leuten / projekten die anforderung, das H.dateien sich fehlerfrei übersetzen lassen müssen wenn man diese an den C-Compiler alleine übergibt. Auch wenn dabei kein bincode dabei rauskommt, garantiert dies doch, das alle in der H.Datei notwengien Includes enthalten sind. Erleichtert auch den umgang z.B. mit einer lib. man muss nicht erst 5 andere h.Dateien includieren (z.B. win API), damit die lib endlich funktioniert.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.