Hallo,
mich würde interessieren, wie ihr mit (teils verschachtelten)
Headerfiles umgeht.
Konkretes Beispiel: Ich verwende eine Headerdatei, in der ich mittels
"typedef" die Kurzschreibweisen für die Datentypen realisiert habe, also
"typedef unsigned char uchar;" etc.
Im C-Sourcefile verweise ich logischerweise auf diese Headerdatei. Die
Headerdatei, welche die Prototypen für die im C-Sourcefile enthaltenen
Funktionen bereitstellt, muss ja diese Kurzschreibweisen auch kennen.
So, jetzt stelle ich mir die Frage, ob es für einen guten Stil
ausreicht, die Headerdatei der Kurzschreibweisen ganz am Anfang jeder
C-Sourcedatei einzubinden, oder in der entsprechenden Headerdatei
(=verschachtelt) oder sogar beides.
Im ersten Fall sieht ein User sofort, dass was zusätzlich "nötig" ist.
Im zweiten Fall ist das nicht offensichtlich, verkürzt aber den
"include"-Block.
Das "Problem" lässt sich noch weiter ausbauen: Mal angenommen, ich habe
ein Sourcefile, welches Funktionen eines anderen Sourcefiles verwendet
(was ja zwangsläufig fast immer der Fall ist). Habe ich die
"include"-Anweisungen im zugehörigen Headerfile ist es wieder nicht
sofort ersichtlich, auf welchen Funktionen aufgebaut wird, aber der
#include-Block ist wiederum kürzer und es stellt sicher, dass immer alle
nötigen #include-Anweisungen vorhanden sind und keine vergessen wurden.
Beispielsweise kann der C51-Compiler von Keil am besten optimieren, wenn
jede Funktion ein eigenes Sourcefile hat, da wäre dann viel Copy&Paste
nötig (was nicht weh tut), aber nachträglich eine Headerdatei in mehrere
betroffene Sourcefiles zu bringen würde schon eher wehtun.
Wie macht ihr das so?
Ralf
Ralf schrieb:> Hallo,>> mich würde interessieren, wie ihr mit (teils verschachtelten)> Headerfiles umgeht.>> Konkretes Beispiel: Ich verwende eine Headerdatei, in der ich mittels> "typedef" die Kurzschreibweisen für die Datentypen realisiert habe, also> "typedef unsigned char uchar;" etc.
Das ist keine gute Idee.
Mitlerweile gibt es dafür brauchbare standardisierte Datentypnamen. OK,
das ist jetzt nicht das Thema. Daher diese Info nur nebenbei
> So, jetzt stelle ich mir die Frage, ob es für einen guten Stil> ausreicht, die Headerdatei der Kurzschreibweisen ganz am Anfang _jeder_> C-Sourcedatei einzubinden, oder in der entsprechenden Headerdatei> (=verschachtelt) oder sogar beides.
Gewöhn dir folgendes an.
Jedes File, egal ob Source oder Header, inkludiert grundsätzlich alles,
was es für sich selbst benötigt.
Im Header kommt ein uchar vor?
Dann inkludiert das Header File auch dasjenige File, welches den uchar
bereitstellt.
In einem C File kommt ein uchar vor?
Dann inkludiert dieses C File auch dasjenige File, welches den uchar
bereitstellt. Und zwar unabhängig davon, ob es nicht auch schon einen
anderen Include gäbe, der den uchar-Header auch inkludieren würde.
Lediglich das eigene Header File kann man davon ausnehmen. Man sieht
also das eigene Header File als die Schnittstellenbeschreibung für sich
selbst an. Und da die Schnittstellenbeschreibung schon einen uchar
bereitgestellt hat, ist das dann in der Implementierung nicht mehr
nötig.
Eine Zeitlang kommt man damit über die Runden:
Ach den Header brauch ich jetzt nicht, ich inkludiere ja sowieso xyz.h
und die zieht mir dann den Header schon rein.
Aber irgendwann ist man in der Situation, das eine winzige Änderung in
einem Header File eine Menge anderer Source Code Files unkompilierbar
macht. Und dann ist die Verzweiflung gross, das alles wieder zu
reparieren.
> sofort ersichtlich, auf welchen Funktionen aufgebaut wird, aber der> #include-Block ist wiederum kürzer
Vergiss die Länge des Include Blocks.
Die ist uninteressant. Wenn du Unmengen includen musst, stehen die
Chancen gut, dass das File sowieso an sich schon zuviel enthält.
> Wie macht ihr das so?
Einfache Regel:
Jedes File included was es benötigt.
Yepp, das kann ich so auch bestätigen.
Headerhygiene wird vor allen Dingen bei großen Projekten sehr wichtig,
da durch exzessives Rekursiv-Includieren die Kompilerzeiten extrem
ansteigen! Bei einem kleinen Bastelprojekt merkt das noch keiner, wenn
man aber so wie wir den Compiler mit 10^6 Zeilen Code foltert, dann
macht es gewaltige Unterschiede in der Vorgehensweise.
Ich habe vor etlichen Jahren gezielt unsere Header entrümpelt und konnte
damit die Kompilierzeit auf 1/4 (!) runterdrücken.
Manchmal ist es auch sinnvoll, im Header benötigte Typen forward zu
deklarieren und erst später im .c/.cpp zu inkludieren.
Es gibt nämlich "nervige" Header, vor allem von externen Libs, die zur
korrekten Kompilation bestimmte defines in den Projektoptionen
benötigen. Und wenn jetzt jemand solch einen Header in einem anderen,
häufig benutzten Header inkludiert, dann müssen alle anderen Projekte
auch diese defines bekommen, was immer für viel Freude sorgt ;-)
Gruß, Oliver