#include<> oder #include““

Ich ärgere mich immer wieder, wenn ich auf GitHub eigentlich interessante Libraries finde und dann feststelle, dass darin die „falschen“ Include-Anweisungen verwendet werden. Aber was ist eigentlich richtig und was ist falsch? Dazu müssen wir erst einmal den Standard bemühen. Da heißt es (frei übersetzt)

#include <...> sucht an den vom System festgelegten Orten nach dem genannten Header.

#include "..." sucht nach der genannten Datei. Wenn diese Suche nicht erfolgreich ist, wird die Suche so fortgesetzt als hätte man den Dateinamen in #include <...> angegeben.

Als erste fällt auf, dass einmal von einem Header und das andere Mal von einer Datei die Rede ist. Ein Grund dafür ist, dass sich der Standard nicht darauf festlegen will, wie die Standard-Header (wie iostream oder cmath) bzw. die darin enthaltenen Definitionen gespeichert werden sollen. In der Praxis sind das meistens Dateien, aber das ist nicht zwingend.

#include <…> heißt also nicht unbedingt „füge an dieser Stelle den Inhalt der genannten Datei ein“, sondern eher „füge hier alle Definitionen ein, die vom Standard in dem genannten Header sein sollten“. Es ist also durchaus möglich, dass der Compiler alle Definitionen aus den Standard-Headern kennt, diese aber erst dann verwendet, wenn der entsprechende Header aktiviert wurde.

Es kann daher nicht falsch sein, wenn man es sich zur Angewohnheit macht, die im Standard definierten Header immer mit #include <…> verwendet. Es ist aber definitiv falsch, wenn man eigene Header-Dateien, also die .h, .hpp oder .hxx Dateien, die im Projekt selbst definiert und verwendet werden, auch mit #include <…> einfügt. Für diese Dateien ist #include „…“ die einzige richtige Lösung.

Aber wie sieht es mit den ganzen anderen Header-Dateien aus, die mit der Entwicklungsumgebung bzw. einem SDK (z.B. die ganzen Windows Header) oder anderen Bibliotheken (z.B. denen von GitHub) aus?

Für die ist #include „…“ jedenfalls nicht falsch. Denn es sind keine Header im Sinne des Standards, sondern Dateien, also ein Fall für #include „…“. Das kann aber bei der großen Zahl von Header-Dateien schnell zu einem Problem werden. Was passiert denn, wenn man zufällig zwei verschiedene Header-Dateien mit gleichen Namen hat. Ich bin einmal, als der cstring Header noch string.h hieß), fast daran verzweifelt, dass der Compiler strlen nicht kannte. Bis sich herausstellte, dass ich #include „string.h“ geschrieben hatte und im Projekt auch eine Datei string.h war, und der Compiler meine Datei statt des Standard-Headers eingefügt hat.

Daraus habe ich meine Schlüsse gezogen und (für mich) Regeln für den Umgang mit #include <…> und #include „…“ aufgestellt. Aber vorher galt es herauszufinden wie mein Compiler (Visual C++) nach Headern und Header-Dateien sucht.

Für #include <…> sucht dieser Compiler

  1. In den mit /I angegebenen Verzeichnissen in der angegebenen Reihenfolge.
  2. In den in der INCLUDE Environment Variablen angegebenen Verzeichnissen in der angegebenen Reihenfolge.

Für #include „…“ wird es etwas komplexer

  1. In dem Verzeichnis, in dem sich die Datei, die das #include Anweisung enthält, befindet.
  2. In den Verzeichnissen der offenen Include-Dateien rückwärts zur Reihenfolge der #include Anweisungen.
  3. In den mit /I angegebenen Verzeichnissen in der angegebenen Reihenfolge.
  4. In den in der INCLUDE Environment Variablen angegebenen Verzeichnissen in der angegebenen Reihenfolge.

Für mich habe ich die folgenden Regeln aufgestellt.

  1. Die Include-Verzeichnisse des Compilers und des Windows SDK werden nicht verändert. Ich überlasse es dem Compiler bzw. dem SDK wie die Dateien gefunden werden (/I Option oder INCLUDE Variable). Für den Zugriff wird immer #include <…> verwendet.
  2. Includes anderer Bibliotheken kommen, wenn möglich, in Unterverzeichnisse eines weiteren Include-Verzeichnisses (C:/ho/dev/inc). Dieses Verzeichnis (nicht die Unterverzeichnisse) kommt ebenfalls in den Suchpfad. Für den Zugriff wird immer #include <library/…> verwendet, wobei library der Name des Unterverzeichnisses von C:/ho/dev/inc ist.
  3. Includes des Projekts selbst oder von Bibliotheken, die Teil des Projekts sind, bleiben, wo sie sind. Auf sie wird mit #include „…“ mit einem relativen Pfad vom Verzeichnis der Datei, die das #include enthält, zugegriffen.
  4. Innerhalb einer Bibliothek in einem Unterverzeichnis von C:/ho/dev/inc wird auf die eigenen, geschachtelten Header mit #include „…“ (evtl. mit einem relativen Pfad) zugegriffen.

Punkt 4 ist bei der Entwicklung eigener Bibliotheken wichtig. Dadurch wird sichergestellt, dass beim erstellen der Bibliothek die aktuellen Header im Source-Verzeichnis verwendet werden und nicht die evtl. veralteten im globalen Include-Verzeichnis.

Eine Antwort auf „#include<> oder #include“““

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert