Hallo zusammen, ich habe zwei Header-Dateien file1.h und file2.h von denen jeweils eine von mehreren C-Dateien includiert werden soll. Um genau zu sein: Ich habe nur eine Header-Datei. Entweder liegt file1.h oder file2.h in der Build-Umgebung vor. Sollten beide vorliegen, ist es kein Problem, wenn beide, oder nur die erste, die gefunden wird, includiert werden. Gibt es die Möglichkeit, dem C-Präprozessor zu sagen, er solle eine Header-Datei nur includieren, wenn sie vorhanden ist? Oder er solle eine Datei includieren, aber wenn es nicht klappt, nicht traurig sein, und einfach weiter machen? Viele Grüße W.T.
Nein. Weder, noch. Was Du machen kannst ist, dein Makefile feststellen zu lassen, ob eine bestimmte Datei vorhanden ist oder nicht und abhängig davon dem Präprozessor entsprechende defines zukommen lassen. Aber das ist reichlich von hinten durch die Brust ins Auge. Es wäre vielleicht besser, erst mal das Problem zu beschreiben, das Du lösen willst, möglicherweise gibt's ja eine bessere Lösung.
Der C++-Programmierer benutzt dazu:
1 | #if __has_include(<f.h>)
|
2 | // ...
|
3 | #endif
|
Ein header-File gehört immer zu einem bestimmten C-File. Insofern ist Deine Frage irgendwie komisch. Stelle doch mal die beiden Files hier hinein, dass können wir Dir besser helfen. Ich vermute, dass in dem headerfile mehr drin ist, als da reingehört.
Walter T. schrieb: > ich habe zwei Header-Dateien > > file1.h und > file2.h Schon das ist sehr ungebräuchlich. Ein Filename sollte immer beschreibend sein, z.B. uart.h, hardware.h, remote.h usw.
Markus F. schrieb: > Es wäre vielleicht besser, erst mal das Problem zu beschreiben, das Du > lösen willst, möglicherweise gibt's ja eine bessere Lösung. Peter D. schrieb: > Ein Filename sollte immer beschreibend sein, z.B. uart.h, hardware.h, > remote.h usw. Das Problem, das ich lösen will, ist, dass ich drei Header-Files habe, die in jedem meiner Projekte vorkommen, deren Inhalt aber schon lange nicht mehr dem Namen entsprechen, den ich ihnen am Anfang meines Schaffens gegeben habe. Eigentlich gehört alles, was in diesen drei Header-Dateien liegt, in zwei Dateien, die anders heißen. Andererseits will ich nicht in meiner kompletten Codebasis herumpfuschen, nur um wieder etwas ordentlicher zu werden. Dabei baue ich sicher wieder neue Fehler ein. Also geht mein Bestreben dahin, die neuen Header zu nutzen, die alten -bis auf weiteres- aber auch noch zu unterstützen und dabei eine Compiler-Warnung auszugeben.
Walter T. schrieb: > Andererseits will ich nicht in meiner kompletten Codebasis > herumpfuschen, nur um wieder etwas ordentlicher zu werden. Dabei baue > ich sicher wieder neue Fehler ein. Einen Tod muss man sterben. Räum' auf, sonst schleppst Du diese überflüssigen Altlasten auf Ewigkeit mit Dir herum. Als erste Abhilfe kannst Du in die alten, falschen Dateien ein #include der richtigen Dateien einbauen, und eine Warnung ausgeben (wie auch immer das Dein Compiler handhabt, mit #pragma message, #pragma warning oder was auch immer). Dann kannst Du unreparierte Bestandsprojekte weiter verwenden, bekommst aber einen Hinweis darauf, daß Du sie reparieren solltest.
Walter T. schrieb: > Gibt es die Möglichkeit, dem C-Präprozessor zu sagen, er solle eine > Header-Datei nur includieren, wenn sie vorhanden ist? Das geht so nicht, aber was Du machen kannst, ist zwei leere Dateien mit dem Namen in ein Verzeichnis legen und dieses Verzeichnis dann an das Ende der Liste, der vom Compiler zu durchsuchende Verzeichnisse setzen. Dann findet der Compiler diese leere Datei, wenn er nicht schon vorher die "richtige" Datei gefunden hat.
Torsten R. schrieb: > Dann findet der Compiler diese leere Datei, wenn er nicht schon vorher > die "richtige" Datei gefunden hat. Sowas nennt man: sich gepflegt selber ins Knie schießen. Irgendwann hat man den dirty hack vergessen und dann sucht man den Fehler völlig verzweifelt an der falschen Stelle. Ich bin immer dankbar, wenn der Compiler mir Fehlermeldungen oder Warnungen gibt, in der Regel hat er damit auch recht.
Peter D. schrieb: > Sowas nennt man: sich gepflegt selber ins Knie schießen. > Irgendwann hat man den dirty hack vergessen und dann sucht man den > Fehler völlig verzweifelt an der falschen Stelle. Peter, der Walter hat eine Frage gestellt; ich habe Ihm eine Lösung angeboten. Ob er damit glücklich wird, oder nicht, wirst weder Du noch ich beurteilen können. In der Realität gibt es immer wieder mal die Notwendigkeit Sachen zu tun, die relativ weit vom Optimium entfernt sind. Was wäre z.B. wenn der Code, den Walter nicht refaktorieren möchte demnächst eh komplett ersetzt werden soll? Würdest Du ihm dazu raten, einige Millionen Zeilen Code erst zu refaktorieren und dann zu entsorgen? Wir kennen die Hintergründe nicht, deswegen sollten wir uns auch mit Urteilen etwas zurück halten, auch wenn wir immer mal wieder gerne raushängen lassen, dass bei uns alles super ist und wir keine Leichen im Keller haben! ;-) mfg Torsten
Torsten R. schrieb: > Wir kennen die Hintergründe nicht, deswegen sollten wir uns auch mit > Urteilen etwas zurück halten, auch wenn wir immer mal wieder gerne > raushängen lassen, dass bei uns alles super ist und wir keine Leichen im > Keller haben! ;-) Richtig, aber fast jedesmal wenn man die Leichen im Keller nicht entsorgt ärgert man sich später drüber. Deshalb ist der beste Rat trotzdem: Rufus Τ. F. schrieb: > Räum' auf, sonst schleppst Du diese überflüssigen Altlasten auf Ewigkeit > mit Dir herum. Und ja auch ich habe beschissenen Code den ich nicht "refactored" habe, obwohl es sinnvoll wäre :-)
Torsten R. schrieb: > Peter, der Walter hat eine Frage gestellt; ich habe Ihm eine Lösung > angeboten. Und ich habe nur auf die Gefahren hingewiesen, die darin lauern. Man kann nicht davon ausgehen, daß die jeder selber erkennt. Es war nicht als persönliche Kritik gemeint.
Torsten R. schrieb: > Peter D. schrieb: > >> Sowas nennt man: sich gepflegt selber ins Knie schießen. >> Irgendwann hat man den dirty hack vergessen und dann sucht man den >> Fehler völlig verzweifelt an der falschen Stelle. > > Peter, der Walter hat eine Frage gestellt; ich habe Ihm eine Lösung > angeboten. Ob er damit glücklich wird, oder nicht, wirst weder Du noch > ich beurteilen können. Wahrscheinlich kann er auch einfach seine C-Datei (bedeutet das jetzt, dass sie abc.C oder abc.c heißt oder das dort C-Code enthalten ist) mit einem C++-Compiler übersetzen und dann das Konstrukt verwenden, was ich oben geschrieben habe ;-)
Wilhelm M. schrieb: > Wahrscheinlich kann er auch einfach seine C-Datei (bedeutet das jetzt, > dass sie abc.C oder abc.c heißt oder das dort C-Code enthalten ist) mit > einem C++-Compiler übersetzen und dann das Konstrukt verwenden, was ich > oben geschrieben habe ;-) Nur, dass das kein C++ ist, sondern eine Erweiterung von clang...
Nope, ist Standard C++17 http://en.cppreference.com/w/cpp/preprocessor/include
:
Bearbeitet durch User
Wilhelm M. schrieb: > Wahrscheinlich kann er auch einfach seine C-Datei (bedeutet das jetzt, > dass sie abc.C oder abc.c heißt oder das dort C-Code enthalten ist) mit > einem C++-Compiler übersetzen und dann das Konstrukt verwenden, was ich > oben geschrieben habe ;-) Ausserdem war es Walters Ziel, den Code nicht anzufassen. Wenn er überall dieses bedingte include einfügt, dann kann er auch dort den neuen Dateinamen einsetzen.
Das kann ich in der Ursprungsfrage nicht entdecken ... Dies war die Frage: > Gibt es die Möglichkeit, dem C-Präprozessor zu sagen, er solle eine > Header-Datei nur includieren, wenn sie vorhanden ist? > > Oder er solle eine Datei includieren, aber wenn es nicht klappt, nicht > traurig sein, und einfach weiter machen?
Es ist sinnvoll, sich zentrale Bibliotheken anzulegen. Nur sind die in der Regel nicht ausgereift, es fallen einem immer wieder noch Erweiterungen und Verbesserungen ein oder auch Bugs sind zu beheben. Daher kopiere ich den gerade aktuellen Stand in das jeweilige Projekt. Wenn man sie nämlich zentral benutzt, hat man das Problem, daß alte Projekte plötzlich nicht mehr laufen, wenn man sie wieder anfassen muß. Mit der lokalen Kopie kann man die Lib pflegen ohne Rücksicht auf die heilige Kuh der Rückwärtskompatibilität. Und man muß keine Verrenkungen mit Macros und Filenamen machen, die den Code unübersichtlich und fehlerträchtig machen. Ich habe schon zu oft Zeit vergeuden müssen, weil eine Lib geändert wurde und der alte Stand für das Projekt nicht oder nur schwer zu restaurieren war.
Wilhelm M. schrieb: > Das kann ich in der Ursprungsfrage nicht entdecken ... > Eigentlich gehört alles, was in diesen drei Header-Dateien liegt, in > zwei Dateien, die anders heißen. > Andererseits will ich nicht in meiner kompletten Codebasis > herumpfuschen, nur um wieder etwas ordentlicher zu werden. Dabei baue > ich sicher wieder neue Fehler ein.
Torsten R. schrieb: > Wilhelm M. schrieb: >> Das kann ich in der Ursprungsfrage nicht entdecken ... > > >> Eigentlich gehört alles, was in diesen drei Header-Dateien liegt, in >> zwei Dateien, die anders heißen. > >> Andererseits will ich nicht in meiner kompletten Codebasis >> herumpfuschen, nur um wieder etwas ordentlicher zu werden. Dabei baue >> ich sicher wieder neue Fehler ein. Das kam erst später zur der Ursprungsfrage dazu! Und trotzdem könnte er genau das mit dem Ansatz machen ... unter der Voraussetzung, dass sein C-Code keine C-Erweiterungen (__flash, etc.) enthält oder bspw. type-punning über union-member macht ...
Walter T. schrieb: > Oder er solle eine Datei includieren, aber wenn es nicht klappt, nicht > traurig sein, und einfach weiter machen? Walter, du bist mal wieder völlig unlogisch. Also: a) Wenn in der .h irgend etwas wichtiges drinsteht, das dein Code tatsächlich braucht, dann MUSS diese .h gefunden und eingebunden werden. Sonst bricht die Übersetzung mit nem Fehler eben ab - eben weil was Wichtiges fehlt. b) Wenn der Compiler nach deinem Wunsche die nicht vorhandene .h ignoriert und einfach weitermacht, dann bricht er ohnehin die Übersetzung wegen Fehler ab. c) Wenn der Compiler ebenfalls nach deinem Wunsche die nicht vorhandene .h ignoriert - und es ergeben sich daraus KEINE Fehler, dann ist diese .h offensichtlich völlig überflüssig. d) es gibt noch nen Sonderfall: Wenn du Tanz auf dem Drahtseil machst, indem du extensiv mit #ifndef xyz.. arbeitest, und dabei im Falle der fehlenden .h die dortigen Inhalte anderweitig ersetzt, dann erzeugst du einen derart miserabel wartbaren Code, daß du dir früher oder später daran den Hals brichst. Also laß sowas lieber sein. Kurzum: Fragen dieser Art kommen nur durch einen unüberlegten Gesamtentwurf zustande. Also befolge lieber den Rat von Rufus und räume auf. Nochwas: ne .h sollte wirklich nur soviel enthalten, wie unbedingt für das Benutzen des Inhaltes der .c von außen nötig ist. Viele auch kommerzielle Hersteller ignorieren das. W.S.
Walter, es fehlt irgendwie noch Info. Die neuen kannst Du doch sofort verwenden. Die alten können doch sofort warnungen werfen, - wenn Du #warning da reinschreibst. - oder wenn Du deren Include-Guard auswertest. Du kannst dabei auch die alten Header entkernen und darin ein #include der neuen setzen. Du kannst dort, wo headerX.h fehlt, einfach eine leere Datei hinlegen. Wenn Du die Suchpfad-Reihenfolge kennst (diese fest ist), kannst Du wahlweise die leere Datei an den Anfang oder ans Ende setzen, je nachdem, was Du erreichen willst. Mache mal ein entsprechendes Beispiel mit 2 alten Headern, einer neuen. Jeweils #include-Guards und eine "Problem-Definition". Und dann dazu die entsprechenden alten und neuen include-Zeilen im C-File.
Hört sich für mich an nach einem Problem das man besser mit vernünftige Versionsverwaltung angehen könnte: svn, git, ... you name it. Walter T. schrieb: > Eigentlich gehört alles, was in diesen drei Header-Dateien liegt, in > zwei Dateien, die anders heißen. Wo liegt dann das Problem? Die alte Dateiten werden von alten, bestehenden Code benutzt. Für neue Projekte legst du die zwei, anders-heißende neue Header-Dateien an und includierst die. Käse fertig. (Mit eine Versionsverwaltung kannst du dann einen Baseline für die alte Projekte anlegen, danach die alte Headers löschen und dich freuen, dass der alte Kram nicht mehr deiner jetztigen Code-Base verseucht;-))
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.