Hey Leute,
İch habe keine Erfahrung mit embedded Programmierung. Nun bin ich in
einem großen Projekt mit dabei, wo ich für die Algortihmenentwicklung
zuständig bin, ohne wirklich kontakt zur Hardware zu haben, jedoch das
Endprodukt eben ein eingebettetes ist.. Ich muss jedoch einige
Module/Bibliotheken bei mir einbinden und benutzen, die früher von
Kollegen für schwächere Hardware entwickelt wurden. Die Software wurde
damals in C entwickelt und meiner Meinung nach haben sie eine schlechte
Struktur/Architektur bzgl der Header, denn was sie sehr oft gemacht
haben bzw machen ist, folgendes:
Es gibt zwei Headerfiles header_a.h und header_b.h und eine Quelldatei
code.c. İn header_a werden unter anderem datentypen definiert und
typedefs gesetzt. In header_b benutzen sie diese Typen wenn sie
Funktionen und weitere Structs deklarieren. Aber sie binden die
Headerdatei header_a nicht ein. Die Definition bzw die Implementierung
erfolgt in der Quelldatei code.c Hier includieren sie natürlich zuerst
header_a und dann header_b, so dass alles kompiliert.
Ich finde, dass es ein schlechter Stil ist, aber vielleicht hat es ja
einen Grund, wie zb dass man im embedded Bereich das eben so macht da
man eben nicht mehrfach inkludieren möchte wegen speicher usw. Wobei das
keine Rolle spielen sollte, da ja die ifdefs das abfangen. Wie gesagt,
vllt gibt es doch iwelche Gründe. Und die software ist riesig, mehrere
zehntausend zeilen code.
Deshalb die Frage, ist das einfach schlechter Stil/Gefrickel oder gibt
es da Gründe?
Headerfiles schrieb:> In header_b benutzen sie diese Typen wenn sie> Funktionen und weitere Structs deklarieren. Aber sie binden die> Headerdatei header_a nicht ein.
Das funktioniert dann halt auch nicht.
Oder benutzen sie die die Typen etwa doch nicht, sondern nur ihre
Vorwärtsdeklarationen?
1
structirgendwas;
2
3
voideineFunktion(structirgendwas*zeiger);
Das macht man nämlich gerne, um Abhängigkeiten von Headern untereinander
aufzulösen. Um einen Zeiger zu vereinbaren, reicht nämlich eine
Vorwärtsdeklaration. Auch um (in C++) eine Referenz oder ein Argument zu
übergeben beispielsweise. Dazu muss garnicht bekannt sein, wie der Typ
selbst aussieht oder wie viel Speicher er belegt (was im Gegensatz dazu
bei der Definition sehr wohl bekannt sein muss).
Das halte ich auch für schlechten Stil. Idealerweise sollte meiner
Meinung nach die Reihenfolge der eingebundenen Header keinen Einfluss
haben und das ist hier nicht so.
Achim S. schrieb:> Vor 30+ Jahren auch kompilierzeit.
Nö, im C file brauch ich nur einen Header einbinden. :-P
Und von ändern hat Keiner was gesagt. Nur sch... Stil.
that 's all schrieb:> Nö, im C file brauch ich nur einen Header einbinden. :-P
Deine Ironie in Ehren, aber bevor der UP das noch nicht kennt:
Wenn Header mehrfach eingebunden sind, dann mussten sie trotz
include-guard jedesmal komplett gelesen werden. Aber das kann es
eigentlich auch nicht gewesen sein, denn es geht ja anscheinend nur um
(selbst zur damaligen Zeit) Mini-Projekte
Headerfiles schrieb:> mehrere zehntausend zeilen code.
Achim S. schrieb:> Wenn Header mehrfach eingebunden sind
Das war keine Ironie:
- Header A bindet Header B ein
- C file bindet nur Headder A ein
- Header A, Header B, C file werden nur 1mal gelesen
Aber es bleibt ein sch... Stil.
(4) The unit header file shall contain #include statements for all other headers required by the unit header. This lets clients use a unit by including a single header file.
6
7
(5) The unit body file shall contain an #include statement for the unit header, before all other #include statements. This lets the compiler verify that all required #include statements are in the header file."
that 's all schrieb:> - Header A bindet Header B ein> - C file bindet nur Headder A ein> - Header A, Header B, C file werden nur 1mal gelesen
Ich habe angenommen, dass Header A-Files (die Typdeclarationen) von
mehreren anderen Header B-Files includiert werden.
Ein H-File, dass nur von einem einzigen anderen H-File includiert wird,
und immer mit dem zusammen gebraucht wird, ist natürlich quatsch.
(Solange es nicht eine Spezielle aufgabe hat, z.B. der Konfiguration
dient und automatisch erzeugt wird oder so)
Achim S. schrieb:> Ein H-File, dass nur von einem einzigen anderen H-File includiert wird,> und immer mit dem zusammen gebraucht wird, ist natürlich quatsch.
Nicht unbedingt: Die Betrachtungsebene ist ein Modul. Ein header mit
Type-Definition kann in verschiedenen Modulen genutzt werden aber je
Modul nur einmal verareitet werden. ;-)
[wenn die beiden Module im gleichen Projekt per header eingebunden
werden, wirds blöd]
Wir reden hier um des Kaisers Bart:
- sch... Stil
- Mehrfacheinbindung im header verhindern
- Reihenfolge der header im Modul sollte keine Rolle spielen
Schönes Wochenende!
Bernd K. schrieb:> Wenn Du Argumentationshilfe brauchst dann verweise a-uf:
...
> (4) The unit header file shall contain #include statements for all other> headers required by the unit header. This lets clients use a unit by> including a single header file.>> (5) The unit body file shall contain an #include statement for the unit> header, before all other #include statements. This lets the compiler> verify that all required #include statements are in the header file."> [/pre]
Das sind die Regeln. Als Argument würde ich mal anführen:
zu (4) damit man als Nutzer nicht lange suchen muss, welche header in
welcher Reihenfolge einzubinden sind.
zu (5) damit zumindest an einer Stelle getestet wird, dass (4)
eingehalten wird.
Diese best practice haben handfeste Vorteile, die man garnicht so
schwammig mit "sauber" beschreiben muss.
mfg Torsten
Das VLC Projekt macht das ebenfalls: Viele Header funktionieren nur wenn
andere Header vorher geladen werden. Man kann also im Standalone Header
nicht wirklich nachvollziehen, was da eigentlich abgeht. Oben wurde
bereits genannt, dass dadurch weniger Code durch den Präprozessor muss.
Ausserdem könnte man damit in C eine Art Templates implementieren.
Nämlich wenn man tatsächlich unterschiedliche Headerkombination nutzt.
Dazu gehört auch noch ein bisschen Makro Magie. Die Nachvollziebarkeit
geht gegen Null und Debuggen wird quasi unmöglich gemacht.
Mir wollte mal ein (Ex-)Kollege weismachen daß include guards nur von
Leuten benutzt werden die nicht imstande (oder zu faul) seien die
Reihenfolge der includes ordentlich zu organisieren, Er halte davon gar
nichts, er brauche keine Include Guards. Auf die Gegenfrage was er denn
dann machen würde wenn zwei Header den selben Header einbinden müssen
hat er mich erst 10 Sekunden angeschaut als hätte ich gefragt aus
welcher Käsesorte der Mond hergestellt ist (diesen Blick hatte er
wirklich gut drauf), danach hat er mir dann kurz und knapp erklärt daß
seine Header grundsätzlich gar nichts includen würden.
Mindestens zweimal am Tag hab ich ihn fluchen hören weil ihm mal wieder
irgendwo an anderer Stelle ein #include verrutscht ist. Und das trotz
(bzw. nachträglich sag ich mal zum Glück) eher mäßiger Komplexität des
betreffenden Projekts.
Bernd K. schrieb:> Mir wollte mal ein (Ex-)Kollege weismachen daß include guards nur von> Leuten benutzt werden die nicht imstande (oder zu faul) seien die> Reihenfolge der includes ordentlich zu organisieren, Er halte davon gar> nichts, er brauche keine Include Guards.
Praktikant?
Bernd K. schrieb:> Mir wollte mal ein (Ex-)Kollege weismachen daß include guards nur von> Leuten benutzt werden die nicht imstande (oder zu faul) seien die> Reihenfolge der includes ordentlich zu organisieren,
Selten so gelacht.
Natürlich müssen Includes so gebaut sein, daß sie völlig unabhängig von
der Reihenfolge laufen. Sie können daher nicht darauf vertrauen, daß im
C-File eine Reihenfolge eingehalten wird. Damit macht man sich das Leben
nur unnötig selber schwer, d.h. man verzettelt sich leicht.
Ich sortiere sie alphabetisch, damit ich Doppelungen leicht sehe.