Domanda Qual è la differenza tra #include e #include "nomefile"?


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

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

1808
2017-08-22 01:40


origine


risposte:


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

Per #include <filename> il preprocessore ricerca in modo dipendente dall'implementazione, normalmente nelle directory di ricerca pre-definite 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 #include <filename> modulo. Questo metodo viene normalmente utilizzato per includere file di intestazione definiti dal programmatore.

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


1044
2017-08-22 01:40



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

In lo standard C, sezione 6.10.2, paragrafi da 2 a 4:

  • 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 il < e > delimitatori e causa la sostituzione di quella 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 quella direttiva con l'intero contenuto del file sorgente identificato dalla sequenza specificata tra il " 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 fosse stata letta

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

    con la sequenza identica contenuta (incluso > caratteri, se presenti) dall'originale   direttiva.

  • 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 include nella direttiva vengono elaborati proprio 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 a < e a > coppia di token di preelaborazione o un paio di " i caratteri sono combinati in un singolo token di pre-elaborazione del nome dell'intestazione definito dall'implementazione.

definizioni:

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

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


594
2017-09-16 21:06



La sequenza di caratteri tra <e> si riferisce in modo univoco a un'intestazione, che non è necessariamente un file. Le implementazioni sono praticamente libere di usare la sequenza di caratteri come desiderano. (Per lo più, tuttavia, trattalo come un nome di file e fai una ricerca nel includere il percorso, come dichiarano gli altri post.)

Se la #include "file" viene utilizzato il modulo, l'implementazione prima cerca un file con il nome specificato, se supportato. Se non (supportato), o se la ricerca fallisce, l'implementazione si comporta come se l'altra (#include <file>) è stata utilizzata la forma.

Inoltre, esiste una terza forma che viene usata quando il #include direttiva non corrisponde a nessuno dei moduli sopra. In questa forma, alcune operazioni preliminari di base (come l'espansione delle macro) vengono eseguite sugli "operandi" di #include direttiva e il risultato dovrebbe corrispondere a una delle due altre forme.


214
2017-09-08 17:43



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

Secondo The Open Group Base Specifications Numero 7,

-IO  elenco

Cambiare l'algoritmo per la ricerca di intestazioni i cui nomi non sono nomi assoluti da cercare nella directory nominata dal elenco percorso 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 il #includere linea, quindi nelle directory denominate -IO opzioni e durano nei soliti posti. Per le intestazioni i cui nomi sono racchiusi tra parentesi angolari ("<>"), l'intestazione deve essere cercata solo nelle directory denominate in -IO opzioni e poi nei soliti posti. Directory nominate -IO le opzioni devono essere cercate nell'ordine specificato. Le implementazioni supportano almeno dieci istanze di questa opzione in un singolo c99 comando invocazione.

Quindi, in un ambiente conforme a POSIX, con un compilatore C compatibile con POSIX, #include "file.h" è probabile che andrà a cercare ./file.h prima, dove . è la directory in cui si trova il file con #include dichiarazione, mentre #include <file.h>, probabilmente sta andando a cercare /usr/include/file.h prima, dove /usr/include è il tuo sistema definito luoghi soliti per le intestazioni (sembra non definito da POSIX).


92
2017-07-20 09:29



Lo fa:

"mypath/myfile" is short for ./mypath/myfile

con . essere o la directory del file in cui il #include è contenuto in, e / o la directory di lavoro corrente del compilatore e / o il default_include_paths

e

<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile

Se ./ è in <default_include_paths>, quindi non fa differenza.

Se mypath/myfile è in un'altra directory di inclusione, il comportamento non è definito.


36
2018-02-08 11:45



Dice la documentazione GCC il seguente sulla differenza tra i due:

Sia i file di intestazione utente che di sistema sono inclusi utilizzando la direttiva di preelaborazione ‘#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. È possibile anteporre le directory a questo elenco con -I opzione (vedi Invocazione).

#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 -iquote opzione.     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 e i nomi macro non vengono espansi. Così, #include <x/*y> specifica l'inclusione di un file di intestazione di sistema denominato 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. Così,#include "x\n\\y"specifica un nome file contenente tre barre rovesciate. (Alcuni sistemi interpretano "\" come un separatore di pathname. Tutti questi anche interpretano ‘/’ allo stesso modo. È più portatile da usare solo ‘/’.)

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


30
2018-01-14 04:52



Il <file> include dice al preprocessore di cercare -I directory e in directory predefinite primo, quindi nella directory del file .c. Il "file" include dice al preprocessore di cercare nella directory del file sorgente primoe quindi 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 dal   sequenza specificata tra i delimitatori <e> e causa il   sostituzione di tale direttiva con l'intero contenuto dell'intestazione.   Come sono specificati i posti o è identificata l'intestazione   implementazione definita.

3 Una direttiva di pre-elaborazione del modulo

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

causa la sostituzione di quella direttiva con l'intero contenuto del file sorgente identificato dal   sequenza specificata tra i "delimitatori"   cercato in un modo definito dall'implementazione. Se questa ricerca è   non supportato, o se la ricerca fallisce, la direttiva viene rielaborata come   se legge

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

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

Nota che "xxx" la forma degrada a <xxx> modulo se il file non viene trovato. Il resto è definito dall'implementazione.


23
2017-09-03 12:17



Secondo lo standard - sì, sono diversi:

  • 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 il < e > delimitatori e causa la sostituzione di quella 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 quella direttiva con l'intero contenuto del file sorgente identificato dalla sequenza specificata tra il " 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 fosse stata letta

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

    con la sequenza identica contenuta (incluso > caratteri, se presenti) dall'originale   direttiva.

  • 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 include nella direttiva vengono elaborati proprio 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 a < e a > coppia di token di preelaborazione o un paio di " i caratteri sono combinati in un singolo token di pre-elaborazione del nome dell'intestazione definito dall'implementazione.

definizioni:

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

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

Si noti che lo standard non indica alcuna relazione tra i modi definiti dall'implementazione. Il primo modulo cerca in un modo definito dall'implementazione e l'altro in un modo (possibilmente altro) definito dall'implementazione. Lo standard specifica anche che alcuni file di inclusione devono essere presenti (ad esempio, <stdio.h>).

Formalmente dovresti leggere il manuale per il tuo compilatore, comunque normalmente (per tradizione) il #include "..." modulo cerca la directory del file in cui il file #include è stato trovato prima, e poi le directory che il #include <...> ricerche di moduli (il percorso di inclusione, ad es. intestazioni di sistema).


16
2017-08-18 06:21



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

Come molti programmatori, ho usato la convenzione informale sull'uso di "myApp.hpp" modulo per i file specifici dell'applicazione e <libHeader.hpp> modulo per i file di sistema di librerie e compilatori, ovvero i file specificati in /I e il INCLUDE variabile ambientale, 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. cioè

#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 veramente preoccupato per questo, usa "./myHeader.h" per un file di inclusione nella stessa directory del codice sorgente (il mio progetto attuale, molto grande, include alcuni nomi di file inclusi sparsi, in realtà un problema di gestione della configurazione).

Ecco il Spiegazione MSDN copiato qui per vostra 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 da ciascuno /I opzione del compilatore.
  4. Lungo i percorsi specificati dal INCLUDE variabile d'ambiente.

Forma di parentesi angolare

Il preprocessore cerca i file include in questo ordine:

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

12
2017-10-14 23:51



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.

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


11
2017-10-25 12:35



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


10
2018-02-08 11:45