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



15 Answers

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 "

language cast memory

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"



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).




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.




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 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 "

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, tuttavia normalmente (per tradizione) il modulo #include "..." cerca nella directory del file in cui è stato trovato prima #include e poi nelle directory che il #include <...> ricerche di modulo (il percorso di inclusione, ad esempio le intestazioni di sistema).




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 .



#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.




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.




#include "filename" // User defined header
#include <filename> // Standard library header.

Esempio:

Il nome del file qui è Seller.h :

#ifndef SELLER_H     // Header guard
#define SELLER_H     // Header guard

#include <string>
#include <iostream>
#include <iomanip>

class Seller
{
    private:
        char name[31];
        double sales_total;

    public:
        Seller();
        Seller(char[], double);
        char*getName();

#endif

Nell'implementazione della classe (ad esempio, Seller.cpp e in altri file che utilizzeranno il file Seller.h ), l'intestazione definita dall'utente deve ora essere inclusa, come indicato di seguito:

#include "Seller.h"



#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.




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.




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.




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 <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.




Credo che le intestazioni incluse tra virgolette vengano cercate negli stessi percorsi di sistema delle parentesi graffe angolari se non vengono trovate nella directory corrente.




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.




Related