c++ header - Qual è la differenza tra #include<filename>e #include "nomefile"?





example language (25)


In C ++, includi un file in due modi:

Il primo è #include che dice al preprocessore di cercare il file nella posizione predefinita predefinita. Questa posizione è spesso una variabile di ambiente INCLUDE che indica il percorso per includere i file.

E il secondo tipo è #include "nomefile" che dice al preprocessore di cercare prima il file nella directory corrente, quindi cercarlo nelle posizioni predefinite che l'utente ha impostato.

Nei linguaggi di programmazione C e C ++, qual è la differenza tra l'uso di parentesi angolari e l'uso di virgolette in un'istruzione di include , come segue?

  1. #include <filename>
  2. #include "filename"



  #include <filename>   (1)     
  #include "filename"   (2)

#include include il file sorgente, identificato dal nome file, nel file sorgente corrente sulla linea immediatamente dopo la direttiva.

La prima versione della direttiva cerca solo le directory standard incluse. La libreria standard C ++, così come la libreria C standard, è inclusa implicitamente nelle directory standard di inclusione. Lo standard include le directory che possono essere controllate dall'utente attraverso le opzioni del compilatore.

La seconda versione cerca dapprima la directory in cui si trova il file corrente e, solo se il file non viene trovato, cerca le directory di inclusione standard.

Nel caso in cui il file non viene trovato, il programma è mal formato.




Grazie per le grandi risposte, esp. Adam Stelmaszczyk e piCookie, e aib.

Come molti programmatori, ho utilizzato la convenzione informale sull'utilizzo del "myApp.hpp" per i file specifici dell'applicazione e del <libHeader.hpp> per i file di sistema di libreria e compilatore, ovvero i file specificati in /I e la variabile di ambiente INCLUDE , per anni ho pensato che fosse lo standard.

Tuttavia, lo standard C afferma che l'ordine di ricerca è specifico dell'implementazione, il che può rendere complicata la portabilità. A peggiorare le cose, usiamo l'inceppamento, che rileva automaticamente dove si trovano i file di inclusione. È possibile utilizzare percorsi relativi o assoluti per i file di inclusione. vale a dire

#include "../../MyProgDir/SourceDir1/someFile.hpp"

Le versioni precedenti di MSVS richiedevano il doppio backslash (\\), ma ora non è necessario. Non so quando è cambiato. Basta usare le barre in avanti per la compatibilità con 'nix (Windows lo accetterà).

Se sei davvero preoccupato, usa "./myHeader.h" per un file di inclusione nella stessa directory del codice sorgente (il mio progetto attuale, molto grande, contiene alcuni nomi di file inclusi sparsi in giro - davvero un problema di gestione della configurazione ).

Ecco la spiegazione MSDN copiata qui per comodità).

Modulo quotato

Il preprocessore cerca i file include in questo ordine:

  1. Nella stessa directory del file che contiene l'istruzione #include.
  2. Nelle directory dei file di inclusione attualmente aperti, nell'ordine inverso in cui
    sono stati aperti. La ricerca inizia nella directory del file di inclusione padre e
    continua verso l'alto attraverso le directory di qualsiasi file include nonni.
  3. Lungo il percorso specificato dall'opzione del compilatore /I
  4. Lungo i percorsi specificati dalla variabile di ambiente INCLUDE .

Forma di parentesi angolare

Il preprocessore cerca i file include in questo ordine:

  1. Lungo il percorso specificato dall'opzione del compilatore /I
  2. Quando la compilazione avviene sulla riga di comando, lungo i percorsi specificati dalla variabile di ambiente INCLUDE .



Il #include <filename> viene utilizzato quando si fa riferimento a un file di sistema. Questo è un file di intestazione che può essere trovato in posizioni predefinite di sistema come /usr/include o /usr/local/include .Per i tuoi file che devono essere inclusi in un altro programma devi usare la #include "filename"sintassi.




La semplice regola generale consiste nell'utilizzare parentesi angolari per includere i file di intestazione forniti con il compilatore. Usa le virgolette per includere qualsiasi altro file di intestazione. La maggior parte dei compilatori lo fa in questo modo.

1.9 - I file di intestazione spiegano in maggior dettaglio le direttive del pre-processore. Se sei un programmatore alle prime armi, quella pagina dovrebbe aiutarti a capire tutto questo. L'ho imparato da qui e l'ho seguito al lavoro.




In pratica, la differenza si trova nella posizione in cui il preprocessore cerca il file incluso.

Per #include <filename> le ricerche del preprocessore dipendono dall'implementazione, normalmente nelle directory di ricerca predefinite dal compilatore / IDE. Questo metodo viene normalmente utilizzato per includere file di intestazione di libreria standard.

Per #include "filename" il preprocessore esegue prima la ricerca nella stessa directory del file contenente la direttiva, quindi segue il percorso di ricerca utilizzato per il modulo #include <filename> . Questo metodo viene normalmente utilizzato per includere file di intestazione definiti dal programmatore.

Una descrizione più completa è disponibile nella documentazione GCC sui percorsi di ricerca .




Almeno per la versione GCC <= 3.0, il modulo parentesi angolare non genera una dipendenza tra il file incluso e quello incluso.

Pertanto, se si desidera generare regole di dipendenza (utilizzando l'opzione GCC -M per l'esempio), è necessario utilizzare il modulo quotato per i file che devono essere inclusi nell'albero delle dipendenze.

(Vedi http://gcc.gnu.org/onlinedocs/cpp/Invocation.html )




L'unico modo per sapere è leggere la documentazione della tua implementazione.

Nello standard C , sezione 6.10.2, i paragrafi da 2 a 4 indicano:

  • Una direttiva di pre-elaborazione del modulo

    #include <h-char-sequence> new-line
    

    ricerca una sequenza di luoghi definiti dall'implementazione per un'intestazione identificata univocamente dalla sequenza specificata tra i delimitatori < e > e causa la sostituzione di tale direttiva con l'intero contenuto dell'intestazione. Come vengono specificati i posti o l'intestazione identificata è definita dall'implementazione.

  • Una direttiva di pre-elaborazione del modulo

    #include "q-char-sequence" new-line
    

    causa la sostituzione di tale direttiva con l'intero contenuto del file di origine identificato dalla sequenza specificata tra i " delimitatori " Il file di origine denominato viene cercato in un modo definito dall'implementazione. Se questa ricerca non è supportata o se la ricerca non riesce , la direttiva viene rielaborata come se leggesse

    #include <h-char-sequence> new-line
    

    con la sequenza identica contenuta (compresi i caratteri, se ce ne sono) dalla direttiva originale.

  • Una direttiva di pre-elaborazione del modulo

    #include pp-tokens new-line
    

    (che non corrisponde a una delle due forme precedenti) è permesso. I token di preelaborazione dopo l' include nella direttiva vengono elaborati esattamente come nel testo normale. (Ogni identificatore attualmente definito come nome macro viene sostituito dall'elenco sostitutivo dei token di preelaborazione). La direttiva risultante dopo tutte le sostituzioni deve corrispondere a uno dei due moduli precedenti. Il metodo con cui una sequenza di token di preelaborazione tra una coppia di token di preelaborazione < e una > o una coppia di " caratteri è combinata in un token di pre-elaborazione del nome di singola intestazione è definita dall'implementazione.

definizioni:

  • h-char: qualsiasi membro del set di caratteri di origine ad eccezione del carattere di nuova riga e >

  • q-char: qualsiasi membro del set di caratteri sorgente ad eccezione del carattere di nuova riga e "




Un #include con parentesi angolari cercherà un "elenco di luoghi dipendente dall'implementazione" (che è un modo molto complicato di dire "intestazioni di sistema") per il file da includere.

Un #include con virgolette cercherà solo un file (e, "in un modo dipendente dall'implementazione", bleh). Il che significa che, in inglese normale, proverà ad applicare il percorso / nome del file che gli viene lanciato e non affiderà un percorso di sistema o manometterà altrimenti.

Inoltre, se #include "" fallisce, viene riletto come #include <> dallo standard.

La g++ ha una descrizione (specifica del compilatore) che, sebbene sia specifica per gcc e non per lo standard, è molto più facile da capire rispetto al discorso in stile avvocato degli standard ISO.




L'ordine dei file di intestazione di ricerca è diverso. <XXX.h> preferisce cercare prima le intestazioni standard mentre "XXX.h" cerca prima i file di intestazione dello spazio di lavoro.




Molte delle risposte qui si concentrano sui percorsi che il compilatore cercherà per trovare il file. Mentre questo è ciò che fa la maggior parte dei compilatori, un compilatore conforme può essere preprogrammato con gli effetti delle intestazioni standard e trattare, ad esempio, #include <list> come switch, e non deve necessariamente esistere come file.

Questo non è puramente ipotetico. C'è almeno un compilatore che funziona in questo modo. Si consiglia di utilizzare #include <xxx> solo con intestazioni standard.




Per #include "" un compilatore normalmente cerca nella cartella del file che contiene quell'inclusione e poi le altre cartelle. Per #include <> il compilatore non cerca la cartella del file corrente.




Modulo 1 - #include "xxx"

Innanzitutto, cerca la presenza del file di intestazione nella directory corrente da dove viene richiamata la direttiva. Se non viene trovato, cerca nella lista preconfigurata delle directory di sistema standard.

Modulo 2 - #include <xxx>

Cerca la presenza del file di intestazione nella directory corrente da dove viene richiamata la direttiva.

L'elenco esatto della directory di ricerca dipende dal sistema di destinazione, da come è configurato GCC e da dove è installato. Puoi trovare l'elenco della directory di ricerca del tuo compilatore GCC eseguendolo con l'opzione -v.

È possibile aggiungere ulteriori directory al percorso di ricerca utilizzando - I dir , che provoca la ricerca della directory dopo la directory corrente (per il modulo di offerta della direttiva) e prima delle directory di sistema standard.

Fondamentalmente, il modulo "xxx" non è altro che ricerca nella directory corrente; se non si trova ricadere nel modulo




#include <file.h> dice al compilatore di cercare l'intestazione nella sua directory "include", ad esempio per MinGW il compilatore file.h in C: \ MinGW \ include \ o ovunque sia installato il compilatore.

#include "file" dice al compilatore di cercare la directory corrente (cioè la directory in cui risiede il file sorgente) per il file .

Puoi usare il flag -I per GCC per dire che, quando incontra una inclusione con parentesi angolate, dovrebbe cercare anche le intestazioni nella directory dopo -I . GCC tratterà la directory dopo il flag come se fosse la directory includes .

Ad esempio, se hai un file chiamato myheader.h nella tua stessa directory, potresti dire #include <myheader.h> se hai chiamato GCC con il flag -I . (indica che dovrebbe cercare include nella directory corrente).

Senza il flag -I , dovrai usare #include "myheader.h" per includere il file, o spostare myheader.h nella directory include del tuo compilatore.




Alcune buone risposte qui fanno riferimento allo standard C ma hanno dimenticato lo standard POSIX, in particolare il comportamento specifico del comando c99 (ad esempio, compilatore C) .

Secondo The Open Group Base Specifications numero 7 ,

-I directory

Modificare l'algoritmo per la ricerca di intestazioni i cui nomi non sono nomi assoluti da cercare nella directory indicata dal nome di percorso della directory prima di cercare nei soliti posti. Pertanto, le intestazioni i cui nomi sono racchiusi tra virgolette ("") devono essere cercati per primi nella directory del file con la riga #include , quindi nelle directory denominate in -I opzioni e l'ultima nei soliti posti. Per le intestazioni i cui nomi sono racchiusi tra parentesi angolari ("<>"), l'intestazione deve essere cercata solo nelle directory denominate in -I opzioni e quindi nei soliti posti. Le directory denominate in -I opzioni devono essere ricercate nell'ordine specificato. Le implementazioni supportano almeno dieci istanze di questa opzione in una singola chiamata di comando c99 .

Quindi, in un ambiente conforme a POSIX, con un compilatore C compatibile con POSIX, #include "file.h" probabilmente ./file.h prima, dove . è la directory in cui è il file con l'istruzione #include , mentre #include <file.h> , è probabile che prima /usr/include/file.h , dove /usr/include è il tuo sistema definito come intestazioni (sembra non definito da POSIX).




  • #include <> è per i file di intestazione predefiniti

Se il file di intestazione è predefinito, dovrai semplicemente scrivere il nome del file di intestazione in parentesi angolari e apparirebbe come questo (supponendo che abbiamo un nome di file di intestazione predefinito iostream):

#include <iostream>
  • #include " " è per i file di intestazione definiti dal programmatore

Se tu (il programmatore) hai scritto il tuo file di intestazione, dovresti scrivere il nome del file di intestazione tra virgolette. Quindi, supponiamo che tu abbia scritto un file di intestazione chiamato myfile.h , quindi questo è un esempio di come myfile.h la direttiva include per includere quel file:

#include "myfile.h"



Il <file> include dice al preprocessore di cercare nelle directory -I e nelle directory predefinite prima , quindi nella directory del file .c. Il "file" include dice al preprocessore di cercare prima la directory del file sorgente e poi tornare a -I e predefinito. Tutte le destinazioni vengono cercate comunque, solo l'ordine di ricerca è diverso.

Lo standard del 2011 riguarda principalmente i file di inclusione in "16.2 Inclusione del file di origine".

2 Una direttiva di pre-elaborazione del modulo

# include <h-char-sequence> new-line

ricerca una sequenza di luoghi definiti dall'implementazione per un'intestazione identificata univocamente dalla sequenza specificata tra i delimitatori <e> e causa la sostituzione di tale direttiva con l'intero contenuto dell'intestazione. Come vengono specificati i posti o l'intestazione identificata è definita dall'implementazione.

3 Una direttiva di pre-elaborazione del modulo

# include "q-char-sequence" new-line

causa la sostituzione di tale direttiva con l'intero contenuto del file di origine identificato dalla sequenza specificata tra i "delimitatori" Il file di origine denominato viene cercato in un modo definito dall'implementazione. Se questa ricerca non è supportata o se la ricerca non riesce , la direttiva viene rielaborata come se leggesse

# include <h-char-sequence> new-line

con la sequenza identica contenuta (compresi i caratteri, se ce ne sono) dalla direttiva originale.

Si noti che il formato "xxx" riduce a <xxx> modulo se il file non viene trovato. Il resto è definito dall'implementazione.




Per vedere l'ordine di ricerca sul tuo sistema utilizzando gcc, in base alla configurazione corrente, puoi eseguire il seguente comando. Puoi trovare maggiori dettagli su questo comando qui

cpp -v /dev/null -o /dev/null

Apple LLVM versione 10.0.0 (clang-1000.10.44.2)
Destinazione: x86_64-apple-darwin18.0.0
Modello di discussione: posix InstalledDir: Library / Developer / CommandLineTools / usr / bin
"/ Libreria / Sviluppatore / CommandLineTools / usr / bin / clang" -cc1-triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror = deprecated-objc-isa-usage -E -disable-free - disable-llvm-verifier -discard-value-names -main-nome-file null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose - munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning = lldb -target-linker-version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 - isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -I / usr / local / include -fdebug-compilation-dir / Users / hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime = macosx-10.14.0 -fmax-type-align = 16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o - -xc / dev / null
clang -cc1 versione 10.0.0 (clang-1000.10.44.2) destinazione predefinita x86_64-apple-darwin18.0.0 ignorando la directory inesistente "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" ignorando inesistente directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." la ricerca inizia qui:
#include <...> la ricerca inizia qui:
/ usr / local / include
/ Libreria / Sviluppatore / CommandLineTools / usr / lib / clang / 10.0.0 / include
/ Libreria / Sviluppatore / CommandLineTools / usr / include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/ Libreria / Sviluppatore / CommandLineTools / SDKs / MacOSX10.14.sdk / System / Library / Frameworks (directory framework)
Fine della lista di ricerca.




#include <filename>

troverà il file corrispondente dalla libreria C ++. significa che se hai un file chiamato hello.h nella cartella della libreria C ++, #include <hello.h>lo caricherà.

Ma,

#include "filename"

troverà il file nella stessa directory in cui si trova il tuo file sorgente.

Inoltre,

#include "path_to_file/filename"

troverà il file nella directory che hai digitato path_to_file.




#include <filename>

viene utilizzato quando si desidera utilizzare il file di intestazione del sistema C / C ++ o le librerie del compilatore. Queste librerie possono essere stdio.h, string.h, math.h, ecc.

#include "path-to-file/filename"

viene utilizzato quando si desidera utilizzare il proprio file di intestazione personalizzato che si trova nella cartella del progetto o da qualche altra parte.

Per ulteriori informazioni sui preprocessori e l'intestazione. Leggi C - Preprocessors .




#include <abc.h>

è usato per includere file di libreria standard. Quindi il compilatore controllerà le posizioni in cui risiedono le intestazioni delle librerie standard.

#include "xyz.h"

dirà al compilatore di includere i file di intestazione definiti dall'utente. Quindi il compilatore controllerà questi file di intestazione nella cartella corrente o -I cartelle definite.




La documentazione GCC dice quanto segue sulla differenza tra i due:

Sia i file di intestazione utente che di sistema sono inclusi utilizzando la direttiva di pre-elaborazione '#include' . Ha due varianti:

#include <file>

Questa variante viene utilizzata per i file di intestazione di sistema. Cerca un file denominato file in un elenco standard di directory di sistema. Puoi anteporre le directory a questo elenco con l'opzione -I (vedi Invocation ).

#include "file"

Questa variante viene utilizzata per i file di intestazione del proprio programma. Cerca un file denominato file prima nella directory contenente il file corrente, quindi nelle directory di preventivo e quindi nelle stesse directory utilizzate per <file> . È possibile anteporre le directory all'elenco delle directory di preventivo con l'opzione -iquote . L'argomento di '#include' , sia delimitato da virgolette o parentesi angolari, si comporta come una costante di stringa in quanto i commenti non vengono riconosciuti ei nomi di macro non vengono espansi. Pertanto, #include <x/*y> specifica l'inclusione di un file di intestazione di sistema chiamato x/*y .

Tuttavia, se i backslash si verificano all'interno del file, sono considerati normali caratteri di testo, non caratteri di escape. Nessuna delle sequenze di escape dei caratteri appropriate alle costanti stringa in C vengono elaborate. Pertanto, #include "x\n\\y" specifica un nome file contenente tre barre rovesciate. (Alcuni sistemi interpretano '\' come un separatore di pathname, tutti interpretano anche '/' allo stesso modo. È molto più semplice usare solo '/' .)

È un errore se c'è qualcosa (diverso dai commenti) sulla linea dopo il nome del file.




Quando usi #include <nomefile>, il pre-processore cerca il file nella directory dei file di intestazione C \ C ++ (stdio.h \ cstdio, string, vector, ecc.). Ma, quando usi # include "nomefile": prima, il pre-processore cerca il file nella directory corrente, e se non lo trova qui - lo cerca nella directory dei file di intestazione C \ C ++.




il "<filename>" cerca nelle posizioni delle librerie C standard

mentre "filename" cerca anche nella directory corrente.

Idealmente, dovresti usare <...> per le librerie C standard e "..." per le librerie che scrivi e sono presenti nella directory corrente.




Ci sono anche require e include_once .

Quindi la tua domanda dovrebbe essere ...

  1. Quando dovrei usare require vs. include ?
  2. Quando dovrei usare require_once vs. require

La risposta a 1 è descritta here .

La funzione require () è identica a include (), tranne per il fatto che gestisce gli errori in modo diverso. Se si verifica un errore, la funzione include () genera un avviso, ma lo script continuerà l'esecuzione. Require () genera un errore irreversibile e lo script si interrompe.

La risposta a 2 può essere trovata here .

L'istruzione require_once () è identica a require (), eccetto PHP controlla se il file è già stato incluso e, in caso affermativo, non lo include (richiede) di nuovo.







c++ c include header-files c-preprocessor