Was ist in den Programmiersprachen C und C ++ der Unterschied zwischen der Verwendung von spitzen Klammern und der Verwendung von Anführungszeichen in einer include
Anweisung wie folgt?
#include <filename>
#include "filename"
c++
c
include
header-files
c-preprocessor
quest49
quelle
quelle
Antworten:
In der Praxis liegt der Unterschied in dem Speicherort, an dem der Präprozessor nach der enthaltenen Datei sucht.
Für
#include <filename>
die Präprozessorsuche in implementierungsabhängiger Weise, normalerweise in Suchverzeichnissen, die vom Compiler / der IDE vorab festgelegt wurden. Diese Methode wird normalerweise verwendet, um Standard-Bibliotheksheaderdateien einzuschließen.Für
#include "filename"
den Präprozessor sucht zuerst im selben Verzeichnis wie die Datei , die Richtlinie enthält, und dann folgt den Suchpfad für die verwendeten#include <filename>
Form. Diese Methode wird normalerweise verwendet, um vom Programmierer definierte Header-Dateien einzuschließen.Eine ausführlichere Beschreibung finden Sie in der GCC- Dokumentation zu Suchpfaden .
quelle
#include <...>
das auf dem System installierte Paket und#include "..."
die nahe gelegene Repository-Version verwendet. Ich könnte diese rückwärts haben. In beiden Fällen wird dem Include-Schutz im gepackten Header ein Unterstrich vorangestellt. (Es könnte eine Konvention für Pakete sein oder vielleicht eine Möglichkeit, das Vermischen der beiden absichtlich zu verhindern, obwohl Versionsqualifizierer für mich sinnvoller wären.)Die einzige Möglichkeit, dies zu erfahren, besteht darin, die Dokumentation Ihrer Implementierung zu lesen.
In der C-Norm , Abschnitt 6.10.2, Absätze 2 bis 4 heißt es:
quelle
Die Zeichenfolge zwischen <und> bezieht sich eindeutig auf einen Header, der nicht unbedingt eine Datei ist. Implementierungen können die Zeichenfolge so gut wie frei verwenden. (Meistens behandeln Sie es jedoch einfach als Dateinamen und führen eine Suche im Include-Pfad durch , wie in den anderen Posts angegeben.)
Wenn das
#include "file"
Formular verwendet wird, sucht die Implementierung zunächst nach einer Datei mit dem angegebenen Namen, sofern dies unterstützt wird. Wenn dies nicht der Fall ist (unterstützt wird) oder wenn die Suche fehlschlägt, verhält sich die Implementierung so, als ob das andere (#include <file>
) Formular verwendet wurde.Es gibt auch ein drittes Formular, das verwendet wird, wenn die
#include
Direktive keinem der oben genannten Formulare entspricht. In dieser Form werden einige grundlegende Vorverarbeitungen (wie die Makroerweiterung) für die "Operanden" der#include
Direktive durchgeführt, und es wird erwartet, dass das Ergebnis mit einer der beiden anderen Formen übereinstimmt.quelle
<
und>
als Schlüssel zum Indizieren in die Bibliothek verwendet.Einige gute Antworten beziehen sich hier auf den C-Standard, haben jedoch den POSIX-Standard vergessen, insbesondere das spezifische Verhalten des Befehls c99 (z. B. C-Compiler) .
Gemäß den Open Group Base Specifications, Ausgabe 7 ,
In einer POSIX-kompatiblen Umgebung mit einem POSIX-kompatiblen C-Compiler
#include "file.h"
wird wahrscheinlich./file.h
zuerst gesucht , wo.
sich das Verzeichnis befindet, in dem sich die Datei mit der#include
Anweisung befindet, während#include <file.h>
wahrscheinlich/usr/include/file.h
zuerst gesucht wird , wo/usr/include
Ihr System definiert ist übliche Stellen für Header (es scheint nicht von POSIX definiert zu sein).quelle
c99
- das ist der POSIX-Name für den C-Compiler. (Der POSIX 2008-Standard konnte sich kaum auf C11 beziehen; das Update 2013 auf POSIX 2008 hat den C-Standard, auf den er sich bezog, nicht geändert.)-L
.In der GCC-Dokumentation wird Folgendes über den Unterschied zwischen beiden angegeben:
quelle
Es tut:
Dabei handelt
.
es sich entweder um das Verzeichnis der Datei, in der sich das#include
befindet, und / oder um das aktuelle Arbeitsverzeichnis des Compilers und / oder um das Verzeichnisdefault_include_paths
und
Wenn in
./
ist<default_include_paths>
, dann macht es keinen Unterschied.Wenn
mypath/myfile
es sich in einem anderen Include-Verzeichnis befindet, ist das Verhalten undefiniert.quelle
#include "mypath/myfile"
ist nicht gleichbedeutend mit#include "./mypath/myfile"
. Wie in der Antwort von piCookie angegeben, weisen doppelte Anführungszeichen den Compiler an, auf implementierungsdefinierte Weise zu suchen - einschließlich der Suche an den angegebenen Stellen#include <...>
. (Eigentlich ist es wahrscheinlich gleichwertig, aber nur, weil zum Beispiel/usr/include/mypath/myfile
als/usr/include/./mypath/myfile
- zumindest auf Unix-ähnlichen Systemen bezeichnet werden kann.)defaultincludepaths
, im Gegensatz zu einer anderen Bedeutung der Angabe.
(wie oben erwähnt). Dies hat die erwartete Konsequenz, dass beide#include "..."
und#include <...>
in dirpathDas
<file>
sind erzählt die Präprozessor in suchen-I
Verzeichnisse und in vordefinierte Verzeichnisse zuerst , dann in das Verzeichnis der C - Datei. Das"file"
Include weist den Präprozessor an, zuerst das Verzeichnis der Quelldatei zu durchsuchen und dann zu zurückzukehren-I
vordefinierte . Alle Ziele werden trotzdem gesucht, nur die Reihenfolge der Suche ist unterschiedlich.Der Standard von 2011 behandelt hauptsächlich die Include-Dateien in "16.2 Aufnahme von Quelldateien".
Beachten Sie, dass
"xxx"
sich das<xxx>
Formular zu einem Formular verschlechtert, wenn die Datei nicht gefunden wird. Der Rest ist implementierungsdefiniert.quelle
-I
Geschäft angegeben ist?-I
.#include <file.h>
Weist den Compiler an, nach dem Header in seinem "Includes" -Verzeichnis zu suchen, z. B. nach MinGW, nach dem der Compilerfile.h
in C: \ MinGW \ include \ suchen würde, oder wo immer Ihr Compiler installiert ist.#include "file"
Weist den Compiler an, das aktuelle Verzeichnis (dh das Verzeichnis, in dem sich die Quelldatei befindet) zu durchsuchenfile
.Sie können das
-I
Flag für GCC verwenden, um anzugeben, dass bei einem Einschluss mit spitzen Klammern auch nach Headern im Verzeichnis danach gesucht werden soll-I
. GCC behandelt das Verzeichnis nach dem Flag so, als wäre es dasincludes
Verzeichnis.Wenn Sie beispielsweise eine Datei
myheader.h
in Ihrem eigenen Verzeichnis haben, können Sie sagen#include <myheader.h>
ob Sie GCC mit dem Flag aufgerufen haben-I .
(was darauf hinweist, dass im aktuellen Verzeichnis nach Includes gesucht werden soll).Ohne das
-I
Flag müssen Sie#include "myheader.h"
die Datei einschließen odermyheader.h
in dasinclude
Verzeichnis Ihres Compilers wechseln .quelle
Standardmäßig - ja, sie sind unterschiedlich:
Beachten Sie, dass der Standard keine Beziehung zwischen den implementierungsdefinierten Manieren feststellt. Das erste Formular sucht auf eine implementierungsdefinierte Weise und das andere auf eine (möglicherweise andere) implementierungsdefinierte Weise. Der Standard legt außerdem fest, dass bestimmte Include-Dateien vorhanden sein müssen (z. B.
<stdio.h>
).Formal müssten Sie das Handbuch für Ihren Compiler lesen, aber normalerweise
#include "..."
durchsucht das Formular (traditionell) das Verzeichnis der Datei, in der das#include
zuerst gefunden wurde, und dann die Verzeichnisse, die das#include <...>
Formular durchsucht (den Include-Pfad, z. B. Systemheader) ).quelle
Vielen Dank für die tollen Antworten, insb. Adam Stelmaszczyk und piCookie und aib.
Wie viele Programmierer habe ich die informelle Konvention verwendet, das
"myApp.hpp"
Formular für anwendungsspezifische Dateien und das<libHeader.hpp>
Formular für Bibliotheks- und Compilersystemdateien zu verwenden, dh Dateien, die in/I
und angegeben sindINCLUDE
jahrelang Umgebungsvariable angegeben sind, und dachte, dies sei der Standard.Der C-Standard besagt jedoch, dass die Suchreihenfolge implementierungsspezifisch ist, was die Portabilität erschweren kann. Um die Sache noch schlimmer zu machen, verwenden wir Jam, der automatisch herausfindet, wo sich die Include-Dateien befinden. Sie können relative oder absolute Pfade für Ihre Include-Dateien verwenden. dh
Ältere Versionen von MSVS erforderten doppelte Backslashes (\\), aber das ist jetzt nicht erforderlich. Ich weiß nicht, wann es sich geändert hat. Verwenden Sie einfach Schrägstriche, um die Kompatibilität mit 'nix zu gewährleisten (Windows akzeptiert dies).
Wenn Sie sich darüber wirklich Sorgen machen, verwenden Sie
"./myHeader.h"
für eine Include-Datei im selben Verzeichnis wie der Quellcode (in meinem aktuellen, sehr großen Projekt sind einige doppelte Include-Dateinamen verstreut - wirklich ein Problem bei der Konfigurationsverwaltung).Hier ist die MSDN-Erklärung, die hier zur Vereinfachung kopiert wurde.
quelle
Zumindest für die GCC-Version <= 3.0 generiert die spitze Klammerform keine Abhängigkeit zwischen der enthaltenen und der eingeschlossenen Datei.
Wenn Sie also Abhängigkeitsregeln generieren möchten (z. B. mit der Option GCC -M), müssen Sie das Anführungszeichen für die Dateien verwenden, die in den Abhängigkeitsbaum aufgenommen werden sollen.
(Siehe http://gcc.gnu.org/onlinedocs/cpp/Invocation.html )
quelle
Für
#include ""
einen Compiler sucht normalerweise den Ordner der Datei , die das beinhalten enthält und dann die anderen Ordner. Denn#include <>
der Compiler durchsucht nicht den Ordner der aktuellen Datei.quelle
<filename>
und"filename"
sucht nach implementierungsdefinierten Stellen.Wenn Sie #include <Dateiname> verwenden, sucht der Vorprozessor nach der Datei im Verzeichnis der C \ C ++ - Headerdateien (stdio.h \ cstdio, Zeichenfolge, Vektor usw.). Wenn Sie jedoch #include "Dateiname" verwenden: Zuerst sucht der Vorprozessor nach der Datei im aktuellen Verzeichnis, und wenn dies nicht der Fall ist, sucht er sie im Verzeichnis der C \ C ++ - Headerdateien.
quelle
#include
bezieht sich die Richtlinie überhaupt nicht ausschließlich auf Dateien.Ein #include mit spitzen Klammern durchsucht eine "implementierungsabhängige Liste von Stellen" (was eine sehr komplizierte Art ist, "Systemheader" zu sagen) nach der einzuschließenden Datei.
Ein #include mit Anführungszeichen sucht nur nach einer Datei (und "in implementierungsabhängiger Weise" bleh). Das heißt, im normalen Englisch wird versucht, den Pfad / Dateinamen anzuwenden, den Sie darauf werfen, und es wird kein Systempfad vorangestellt oder anderweitig manipuliert.
Wenn #include "" fehlschlägt, wird es vom Standard erneut als #include <> gelesen.
Die gcc-Dokumentation enthält eine (compilerspezifische) Beschreibung, die zwar spezifisch für gcc und nicht für den Standard ist, aber viel einfacher zu verstehen ist als die anwaltliche Rede über die ISO-Standards.
quelle
zlib.h
in meinen 'Benutzer'-Suchpfaden eine andere Version im Systemsuchpfad. Enthält dann#include <zlib.h>
die Systemversion und#include "zlib.h"
meine eigene?Beispiel:
Der Dateiname hier ist
Seller.h
:In der Klassenimplementierung (z. B.
Seller.cpp
und in anderen Dateien, die die Datei verwendenSeller.h
) sollte der vom Benutzer definierte Header nun wie folgt enthalten sein:quelle
#include <>
ist für vordefinierte Header-DateienWenn die Header-Datei vordefiniert ist, schreiben Sie einfach den Namen der Header-Datei in eckige Klammern und es sieht folgendermaßen aus (vorausgesetzt, wir haben einen vordefinierten Header-Dateinamen iostream):
#include " "
ist für Header-Dateien, die der Programmierer definiertWenn Sie (der Programmierer) Ihre eigene Header-Datei geschrieben haben, würden Sie den Namen der Header-Datei in Anführungszeichen schreiben. Angenommen, Sie haben eine Header-Datei mit dem Namen geschrieben
myfile.h
. Dies ist ein Beispiel dafür, wie Sie die include-Direktive verwenden würden, um diese Datei einzuschließen:quelle
Viele der Antworten hier konzentrieren sich auf die Pfade, die der Compiler durchsucht, um die Datei zu finden. Während dies bei den meisten Compilern der Fall ist, darf ein konformer Compiler mit den Auswirkungen der Standardheader vorprogrammiert werden und
#include <list>
beispielsweise als Schalter behandelt werden, und er muss überhaupt nicht als Datei vorhanden sein.Dies ist nicht rein hypothetisch. Es gibt mindestens einen Compiler, der so funktioniert. Die Verwendung
#include <xxx>
nur mit Standard-Headern wird empfohlen.quelle
wird verwendet, um Standardbibliotheksdateien einzuschließen. Der Compiler überprüft also die Speicherorte, an denen sich Standardbibliotheksheader befinden.
weist den Compiler an, benutzerdefinierte Header-Dateien einzuschließen. Der Compiler sucht also im aktuellen Ordner oder in den
-I
definierten Ordnern nach diesen Header-Dateien .quelle
Fügen Sie in C ++ eine Datei auf zwei Arten hinzu:
Das erste ist #include, das den Präprozessor anweist, nach der Datei am vordefinierten Standardspeicherort zu suchen. Dieser Speicherort ist häufig eine INCLUDE-Umgebungsvariable, die den Pfad zum Einschließen von Dateien angibt.
Der zweite Typ ist #include "Dateiname", der den Präprozessor anweist, zuerst nach der Datei im aktuellen Verzeichnis und dann an den vordefinierten Speicherorten zu suchen, die der Benutzer eingerichtet hat.
quelle
Formular 1 - #include <xxx>
Sucht zunächst nach dem Vorhandensein einer Header-Datei im aktuellen Verzeichnis, von dem aus die Direktive aufgerufen wird. Wird es nicht gefunden, wird in der vorkonfigurierten Liste der Standardsystemverzeichnisse gesucht.
Formular 2 - #include "xxx"
Dies sucht nach dem Vorhandensein einer Header-Datei im aktuellen Verzeichnis, von dem aus die Direktive aufgerufen wird.
Die genaue Liste der Suchverzeichnisse hängt vom Zielsystem ab, davon, wie GCC konfiguriert ist und wo es installiert ist. Sie finden die Suchverzeichnisliste Ihres GCC-Compilers, indem Sie sie mit der Option -v ausführen.
Sie können dem Suchpfad zusätzliche Verzeichnisse hinzufügen, indem Sie - I dir verwenden . Dadurch wird dir nach dem aktuellen Verzeichnis (für die Anführungszeichenform der Direktive) und vor den Standardsystemverzeichnissen durchsucht.
Grundsätzlich ist die Form "xxx" nichts anderes als die Suche im aktuellen Verzeichnis; Wenn nicht gefunden, fällt das Formular zurück
quelle
#include "header.h"
Formulars ist nicht korrekt, @personal_cloud. Ich halte die Antwort von piCookie und Yann Droneaud für am relevantesten, da sie identifizieren, woher ihre Informationen stammen. Ich finde die am besten gewählte Antwort auch nicht ganz zufriedenstellend.Das
#include <filename>
wird verwendet, wenn auf eine Systemdatei verwiesen wird. Dies ist eine Header-Datei, die sich an Standardspeicherorten des Systems wie/usr/include
oder befindet/usr/local/include
. Für Ihre eigenen Dateien, die in einem anderen Programm enthalten sein müssen, müssen Sie die#include "filename"
Syntax verwenden.quelle
Idealerweise verwenden Sie <...> für Standard-C-Bibliotheken und "..." für Bibliotheken, die Sie schreiben und die im aktuellen Verzeichnis vorhanden sind.
quelle
Die einfache allgemeine Regel besteht darin, spitze Klammern zu verwenden, um Header-Dateien einzuschließen, die mit dem Compiler geliefert werden. Verwenden Sie doppelte Anführungszeichen, um andere Header-Dateien einzuschließen. Die meisten Compiler machen das so.
1.9 - Header-Dateien erläutern ausführlicher die Anweisungen vor dem Prozessor. Wenn Sie ein Anfänger sind, sollte diese Seite Ihnen helfen, all das zu verstehen. Ich habe es von hier gelernt und habe es bei der Arbeit verfolgt.
quelle
#include <filename>
wird verwendet, wenn Sie die Header-Datei des C / C ++ - Systems oder der Compiler-Bibliotheken verwenden möchten. Diese Bibliotheken können stdio.h, string.h, math.h usw. sein.
#include "path-to-file/filename"
wird verwendet, wenn Sie Ihre eigene benutzerdefinierte Header-Datei verwenden möchten, die sich in Ihrem Projektordner oder an einer anderen Stelle befindet.
Weitere Informationen zu Präprozessoren und Headern. Lesen Sie C - Präprozessoren .
quelle
#include <filename>
#include "filename"
#include <filename>
und durchsucht die Header-Datei dort, wo die System-Header-Dateien gespeichert sind.#include <filename>
.quelle
Um die Suchreihenfolge auf Ihrem System mit gcc basierend auf der aktuellen Konfiguration anzuzeigen, können Sie den folgenden Befehl ausführen. Weitere Details zu diesem Befehl finden Sie hier
cpp -v /dev/null -o /dev/null
quelle
Schließt eine Datei ein, in der das Standardverschlussverzeichnis enthalten ist.
Schließt eine Datei in das aktuelle Verzeichnis ein, in dem sie kompiliert wurde.
quelle
Es gibt zwei Möglichkeiten, eine # include-Anweisung zu schreiben. Dies sind:
Die Bedeutung jeder Form ist
Dieser Befehl sucht nach der Datei
mylib.h
im aktuellen Verzeichnis sowie nach der angegebenen Liste von Verzeichnissen, wie im Include-Suchpfad angegeben, der möglicherweise eingerichtet wurde.Dieser Befehl sucht
mylib.h
nur in der angegebenen Liste von Verzeichnissen nach der Datei .Der Include-Suchpfad ist nichts anderes als eine Liste von Verzeichnissen, die nach der enthaltenen Datei durchsucht werden sollen. Mit verschiedenen C-Compilern können Sie den Suchpfad auf verschiedene Arten festlegen.
quelle