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.
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.