Qual è la differenza tra #include <nomefile> e #include “nomefile”?


2357

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

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



Per il comportamento di Visual Studio, consultare: docs.microsoft.com/en-us/cpp/preprocessor/…
smwikipedia

Risposte:


1405

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

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

Il #include "filename"preprocessore cerca prima nella stessa directory del file contenente la direttiva, quindi segue il percorso di ricerca utilizzato per il #include <filename>modulo. 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 .


135
L'affermazione: "il preprocessore cerca nella stessa directory ..." può essere vero in pratica, ma lo standard afferma che il file di origine denominato è "cercato in un modo definito dall'implementazione". Vedi la risposta di piCookie.
Richard Corden,

60
Mentre la tua risposta può sembrare "vera", poiché questo è il numero di implementazioni che funzionano per convenzione, dovresti dare un'occhiata da vicino alle risposte di aib e piCookie. Entrambi sottolineano (supportato dalla formulazione dello standard C) che la vera distinzione è l'inclusione di un "header" rispetto all'inclusione di un "file sorgente" (e no, questo non significa ".h" vs. ". c "). "File sorgente" in questo contesto può essere (e di solito è, e quasi sempre dovrebbe essere) un file ".h". Un'intestazione non deve necessariamente essere un file (un compilatore potrebbe ad esempio includere un'intestazione codificata staticamente, non in un file).
Dan Molding,

5
"... il preprocessore cerca nella stessa directory del file che si sta compilando per includere il file." Questa affermazione non è completamente corretta. Ero interessato a questa domanda perché ero curioso di sapere quale fosse la risposta effettiva, ma so che questo non è vero perché almeno con gcc quando specifichi un percorso di inclusione aggiuntivo con -I che cercherà i file specificati con #include "nomefile. h "
Gabriel Southern

9
A chi non piace la risposta, per favore, fai un esempio pratico, dove è sbagliato.
0kats

1
Abbastanza sicuro, di recente ho mescolato queste sintassi includendo le intestazioni dalla libreria "stessa" e ho finito con errori di ridefinizione. Se ho capito bene, ho #include <...>usato il pacchetto installato sul sistema e ho #include "..."usato la versione del repository vicina. Potrei avere quelli al contrario. In entrambi i casi, la protezione include nell'intestazione del pacchetto è preceduta da un carattere di sottolineatura. (Potrebbe essere una convenzione per i pacchetti o forse un modo per impedire deliberatamente di mescolare i due, anche se i qualificatori di versione avrebbero più senso per me.)
John P

714

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

Nella norma C , sezione 6.10.2, i paragrafi da 2 a 4 stabiliscono:

  • Una direttiva di preelaborazione del modulo

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

    ricerche una sequenza di luoghi di attuazione definite per un'intestazione identificato univocamente dalla sequenza specificata tra la <e >delimitatori, e provoca la sostituzione di tale direttiva da parte intero contenuto del intestazione . Il modo in cui i luoghi vengono specificati o l'header identificato è definito dall'implementazione.

  • Una direttiva di preelaborazione del modulo

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

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

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

    con la stessa sequenza contenuta (inclusi eventuali >caratteri) dalla direttiva originale.

  • Una direttiva di preelaborazione del modulo

    #include pp-tokens new-line

    (che non corrisponde a uno dei due moduli precedenti) è consentito. I token di preelaborazione successivi includenella direttiva vengono elaborati proprio come nel testo normale. (Ogni identificatore attualmente definito come nome di macro è sostituito dal suo elenco di token di preelaborazione di sostituzione.) La direttiva risultante dopo tutte le sostituzioni deve corrispondere a una delle due forme precedenti. Il metodo con cui una sequenza di token di preelaborazione tra una <e una >coppia di token di preelaborazione o una coppia di" caratteri viene combinata in un singolo token di preelaborazione del nome di intestazione è definito dall'implementazione.

definizioni:

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

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


108
Rilevante: implementazione in g ++ e in visual c ++
Alexander Malakhov,

27
@piCookie sia <nomefile> che "nome file" cercano luoghi definiti dall'implementazione. Quindi qual è la differenza?
onmyway133

15
@Stefan, sto solo citando lo standard che non dice nulla su INCLUDE_PATH. L'implementazione potrebbe farlo, e la mia no. La domanda originale era genericamente C e non specificamente gcc (che non credo usi INCLUDE_PATH) o Microsoft C (che penso lo faccia) o qualsiasi altra cosa, quindi non è possibile rispondere genericamente, ma invece si deve fare riferimento alla documentazione di ogni implementazione.
piCookie,

12
Come in tutte queste situazioni, esempi concreti (soprattutto di scenari comuni) sono molto utili e ugualmente apprezzati. Le risposte generiche inutilmente ottuse non hanno un uso tanto pratico.
vargonian

132
"Ecco come lo standard C può essere dettagliato e non rispondere alla tua domanda"
anatolyg

287

La sequenza di caratteri tra <e> si riferisce in modo univoco a un'intestazione, che non è necessariamente un file. Le implementazioni sono praticamente gratuite per usare la sequenza di caratteri come desiderano. (Principalmente, tuttavia, basta trattarlo come un nome di file e fare una ricerca in percorso di inclusione , come affermano gli altri post.)

Se la #include "file" viene utilizzato modulo, l'implementazione cerca innanzitutto un file con il nome specificato, se supportato. In caso contrario (supportato) o se la ricerca non riesce, l'implementazione si comporta come se #include <file>fosse utilizzato l'altro modulo ( ).

Inoltre, esiste un terzo modulo che viene utilizzato quando la #includedirettiva non corrisponde a nessuno dei moduli sopra. In questa forma, alcuni preelaborazioni di base (come l'espansione macro) vengono eseguiti sugli "operandi" della #includedirettiva e il risultato dovrebbe corrispondere a una delle altre due forme.


50
+1, questa è probabilmente la risposta più concisa e corretta qui. Secondo lo standard (che piCookie cita nella sua risposta), l'unica vera differenza è "header" rispetto a "file sorgente". Il meccanismo di ricerca è definito dall'implementazione in entrambi i modi. L'uso delle virgolette doppie implica che si intende includere un "file sorgente", mentre le parentesi angolari indicano che si intende includere un "header" che, come dici tu, potrebbe non essere affatto un file.
Dan Molding,

3
Vedi il commento di Dan Moulding alla risposta di quest49; le intestazioni standard non devono essere in formato file, possono essere integrate.
aib

10
Ho letto questo "intestazioni standard non devono essere in formato file" per un decennio. Vuoi fornire un esempio reale?
Maxim Egorushkin,

12
@Maxim Yegorushkin: non riesco nemmeno a pensare a nessun esempio esistente nel mondo reale; tuttavia, non esiste un compilatore C11 completo per MS-DOS a meno che le intestazioni non debbano essere file. Questo perché alcuni dei nomi delle intestazioni C11 non sono compatibili con la limitazione "8.3" del nome file MS-DOS.
Dan Molding,

18
@MaximEgorushkin: il compilatore C VAX / VMS ha conservato tutte le intestazioni della libreria di runtime C in un singolo file di libreria testuale (simile a un archivio unix) e ha usato la stringa tra <e >come chiave per indicizzarla nella libreria.
Adrian McCarthy,

117

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

Secondo il numero 7 delle specifiche di base del gruppo aperto ,

-I directory

Modificare l'algoritmo per la ricerca di intestazioni i cui nomi non sono nomi di percorso assoluti da cercare nella directory denominata dal nome di percorso della directory prima di cercare nei soliti luoghi. Pertanto, le intestazioni i cui nomi sono racchiusi tra virgolette ("") devono essere ricercate prima nella directory del file con la riga #include , quindi nelle directory denominate nelle opzioni -I e infine nei soliti posti. Per le intestazioni i cui nomi sono racchiusi tra parentesi angolari ("<>"), l'intestazione deve essere cercata solo nelle directory denominate nelle opzioni -I e quindi nei normali luoghi. Directory denominate in -I opzioni devono essere ricercate nell'ordine specificato.invocazione del comando c99 .

Quindi, in un ambiente conforme a POSIX, con un compilatore C conforme a POSIX, #include "file.h"è probabile che cercherà per ./file.hprimo, dove si .trova la directory in cui si trova il file con l' #includeistruzione, mentre #include <file.h>, è probabile che cercherà per /usr/include/file.hprima, dove /usr/includeè definito il sistema luoghi abituali per le intestazioni (non sembra definito da POSIX).


1
Qual è la fonte esatta del testo? Proviene dalla parte normativa di IEEE Std 1003.1, 2013?
osgx,

7
@osgx: quel testo (o qualcosa di estremamente simile) si trova nella specifica POSIX per c99- che è il nome POSIX per il compilatore C. (Lo standard POSIX 2008 potrebbe a malapena fare riferimento a C11; l'aggiornamento del 2013 a POSIX 2008 non ha modificato lo standard C a cui si riferiva.)
Jonathan Leffler

1
Anche questo è stato il mio primo pensiero. La manpage di gcc include questo come altri. C'è anche una cosa simile per le biblioteche - -L.
Pryftan,

50

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

Sia i file di intestazione utente che quelli di sistema sono inclusi usando la direttiva di preelaborazione ‘#include’. Ha due varianti:

#include <file>

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

#include "file"

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

Tuttavia, se si verificano barre rovesciate all'interno del file, vengono considerati normali caratteri di testo, non caratteri di escape. Nessuna delle sequenze di escape di caratteri appropriate alle costanti di stringa in C viene elaborata. Pertanto, #include "x\n\\y"specifica un nome file contenente tre barre rovesciate. (Alcuni sistemi interpretano "\" come un separatore di percorso. Tutti questi interpretano ‘/’allo stesso modo. È più portabile solo da usare ‘/’.)

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


46

Fa:

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

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

e

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

Se ./è dentro <default_include_paths>, allora non fa differenza.

Se si mypath/myfiletrova in un'altra directory include, il comportamento non è definito.


12
No, #include "mypath/myfile"non è equivalente a #include "./mypath/myfile". Come dice la risposta di piCookie, le doppie virgolette indicano al compilatore di cercare in un modo definito dall'implementazione, che include la ricerca nei luoghi specificati #include <...>. (In realtà, probabilmente è equivalente, ma solo perché, per esempio, /usr/include/mypath/myfilepuò essere indicato come /usr/include/./mypath/myfile- almeno su sistemi simili a Unix.)
Keith Thompson

1
@Keith Thompson: Esatto, stavo pensando alla mia scatola di Linux. Evidentemente potrebbe essere diverso. Sebbene in pratica, Windows come sistema operativo non Posix interpreta / come separatore di percorso ed esiste anche.
Stefan Steiger,

1
l' opzione -L dirpath aggiunge quindi dirpath a defaultincludepaths, invece di dare un altro significato a .(come indicato sopra). Ciò ha la conseguenza attesa che entrambi #include "..."e la #include <...>ricerca in dirpath
Protongun

1
Penso che questa risposta sia errata, dal momento che implica che le intestazioni incluse tra virgolette doppie siano sempre ricercate nella directory di lavoro corrente. Il meccanismo di ricerca è molto più dettagliato; questa risposta è incompleta. Non sto aggiungendo questo commento per lamentarmi o lamentarmi, ma perché il sistema mi chiede di aggiungere un commento per spiegare perché ho votato questa risposta.
Carlo Wood,

39

Il <file>includono dice al preprocessore di cercare in -Icartelle e nelle directory predefinite prima , poi nella directory del file .c. Il "file"includono dice al preprocessore di cercare directory del file di origine prima , e poi tornare a -Ie predefiniti. Tutte le destinazioni vengono comunque ricercate, solo l'ordine di ricerca è diverso.

Lo standard del 2011 discute principalmente dei file di inclusione in "16.2 Inclusione dei file di origine".

2 Una direttiva di preelaborazione del modulo

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

cerca una sequenza di posizioni definite dall'implementazione per un'intestazione identificata in modo univoco dalla sequenza specificata tra i delimitatori <e> e provoca la sostituzione di quella direttiva con l'intero contenuto dell'intestazione. Come vengono specificati i luoghi o identificato l'intestazione viene definita l'implementazione.

3 Una direttiva di preelaborazione del modulo

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

provoca la sostituzione di tale direttiva con l'intero contenuto del file di origine identificato dalla sequenza specificata tra i "delimitatori. Il file di origine indicato viene cercato in 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 stessa sequenza contenuta (compresi> eventuali caratteri) dalla direttiva originale.

Si noti che il "xxx"modulo si degrada per <xxx>formare se il file non viene trovato. Il resto è definito dall'implementazione.


4
Potresti fornire un riferimento a dove nello standard C -Iè specificata questa attività?
juanchopanza,

1
Non vedo alcun riferimento a -I.
juanchopanza,

2
Questa è la parte "definita dall'implementazione".

28

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

#include "file"indica al compilatore di cercare la directory corrente (ovvero la directory in cui risiede il file sorgente) file.

Puoi usare il -Iflag per GCC per dirgli che, quando incontra un'inclusione con parentesi angolate, dovrebbe anche cercare le intestazioni nella directory dopo -I. GCC tratterà la directory dopo il flag come se fosse la includesdirectory.

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

Senza il -Iflag, dovrai utilizzare #include "myheader.h"per includere il file o passare myheader.halla includedirectory del tuo compilatore.


22

Per lo standard - sì, sono diversi:

  • Una direttiva di preelaborazione del modulo

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

    ricerche una sequenza di luoghi di attuazione definite per un'intestazione identificato univocamente dalla sequenza specificata tra la <e >delimitatori, e provoca la sostituzione di tale direttiva dall'intero contenuto dell'intestazione. Il modo in cui i luoghi vengono specificati o l'header identificato è definito dall'implementazione.

  • Una direttiva di preelaborazione del modulo

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

    provoca la sostituzione di tale direttiva con l'intero contenuto del file sorgente 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 fallisce, la direttiva viene rielaborata come se fosse letta

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

    con la stessa sequenza contenuta (inclusi eventuali >caratteri) dalla direttiva originale.

  • Una direttiva di preelaborazione del modulo

    #include pp-tokens new-line

    (che non corrisponde a uno dei due moduli precedenti) è consentito. I token di preelaborazione successivi includenella direttiva vengono elaborati proprio come nel testo normale. (Ogni identificatore attualmente definito come nome di macro è sostituito dal suo elenco di token di preelaborazione di sostituzione.) La direttiva risultante dopo tutte le sostituzioni deve corrispondere a una delle due forme precedenti. Il metodo mediante il quale una sequenza di token di preelaborazione tra una <e una >coppia di token di preelaborazione o una coppia di" caratteri viene combinata in un singolo token di preelaborazione del nome di intestazione è definito dall'implementazione.

definizioni:

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

  • q-char: qualsiasi membro del set di caratteri di origine tranne il 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 (forse altro) definito dall'implementazione. La norma specifica inoltre che devono essere presenti alcuni file di inclusione (ad esempio <stdio.h>).

Formalmente dovresti leggere il manuale del tuo compilatore, tuttavia normalmente (per tradizione) il #include "..."modulo cerca nella directory del file in cui è #includestato trovato prima il file, quindi nelle directory in cui #include <...>cerca il modulo (il percorso include, ad esempio le intestazioni di sistema ).


2
Questo è principalmente lo stesso testo della risposta di piCookie di sette anni prima.
Kyle Strand,

5
@KyleStrand Questo perché lo stesso testo è una citazione della sezione pertinente nello standard - quel testo dovrebbe essere identico. La risposta effettiva non è lo stesso testo ed è in qualche modo diversa - mentre riconosco anche che sarà scritto nella documentazione per l'implementazione, noto anche che c'è anche un modo tradizionale in cui vengono interpretati (che la maggior parte o tutti i compilatori che ho usato rispetta) .
stelle il

2
IMO questa è la risposta migliore qui, perché copre sia ciò che dice lo standard sia ciò che la maggior parte dei compilatori effettivamente fa.
lavaggio:

17

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

Come molti programmatori, ho usato la convenzione informale di utilizzare il "myApp.hpp"modulo per i file specifici dell'applicazione e il <libHeader.hpp>modulo per i file di sistema della libreria e del compilatore, ovvero i file specificati in /Ie la INCLUDEvariabile di ambiente, per anni pensando che fosse lo standard.

Tuttavia, lo standard C afferma che l'ordine di ricerca è specifico dell'implementazione, il che può complicare la portabilità. A peggiorare le cose, usiamo jam, che individua automagicamente dove sono i file include. È 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 doppie barre rovesciate (\\), ma ora non è necessario. Non so quando è cambiato. Basta usare le barre per la compatibilità con 'nix (Windows lo accetterà).

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

Ecco la spiegazione MSDN copiata qui per comodità).

Modulo tra virgolette

Il preprocessore cerca i file di inclusione in questo ordine:

  1. Nella stessa directory del file che contiene l'istruzione #include.
  2. Nelle directory dei file attualmente aperti includere i file, nell'ordine inverso in cui
    sono stati aperti. La ricerca inizia nella directory del file include parent e
    continua verso l'alto attraverso le directory di tutti i file include nonni.
  3. Lungo il percorso specificato da ciascuna /Iopzione del compilatore.
  4. Lungo i percorsi specificati dalla INCLUDEvariabile d'ambiente.

Forma a parentesi angolare

Il preprocessore cerca i file di inclusione in questo ordine:

  1. Lungo il percorso specificato da ciascuna /Iopzione del compilatore.
  2. Durante la compilazione si verifica sulla riga di comando, lungo i percorsi specificati dalla INCLUDEvariabile di ambiente.

16

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 esempio), è necessario utilizzare il modulo tra virgolette per i file che devono essere inclusi nell'albero delle dipendenze.

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


1
Sì, esistono diversi modi per generare dipendenze. Questo è uno di questi, ma non è l'unico.
Pryftan,

15

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


1
Non sono sicuro del motivo per cui le persone non sono d'accordo.
Maxim Egorushkin,

Sospetto perché la maggior parte delle persone compili solo i file nel loro CWD. Se sei nella directory foo e stai compilando foo / unittest / bar.c e include bar.h, allora "bar.h" funziona e <bar.h> no.

1
Le persone @Maxim non sono d'accordo perché il comportamento che descrivi non è lo standard C.
osvein

2
@Spookbuster Esatto, lo standard dice entrambi <filename>e "filename"cerca luoghi definiti dall'implementazione.
Maxim Egorushkin,

14

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


1
Dopo che una risposta perfetta era disponibile da anni, perché inviarne una, è palesemente sbagliato? Anche se comune, la #includedirettiva non è affatto strettamente correlata ai file.
Indispensabile dal

@Ispettabile, spiega perché non è affatto correlato ai file.
Behrooz Karjoo,

11

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

Un #include tra virgolette cercherà solo un file (e, "in modo dipendente dall'implementazione", bleh). Il che significa che, in inglese normale, proverà ad applicare il percorso / nome file che si lancia in esso e non anteporre un percorso di sistema o manometterlo in altro modo.

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

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


Tuttavia, l'uso di parentesi angolari o virgolette non influisce sul modo in cui i file sono inclusi, è esattamente lo stesso: il preprocessore crea essenzialmente un file di origine di grandi dimensioni copiando e inviando il codice da file di inclusione a file di origine originale, prima di dare al compilatore (il preprocessore fa altro, come #define sostentamento, valutazione #if, ecc. ma l'elaborazione #include è così semplice)
Loghorn

E i conflitti? ad esempio dire che ho zlib.hpercorsi di ricerca "utente" ed esiste una versione diversa nel percorso di ricerca del sistema, quindi #include <zlib.h>include la versione del sistema e #include "zlib.h"include la mia?
the_mandrill

Aha, ha risposto alla mia domanda: stackoverflow.com/questions/21593/...
the_mandrill

Grazie per aver riconosciuto che sia lo standard (s) che le convenzioni di implementazione tipiche sono entrambi rilevanti qui, piuttosto che dichiarare semplicemente che è inconoscibile perché non è specificato dallo standard.
Kyle Strand,

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

Esempio:

Il nome 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.cppe in altri file che utilizzeranno il file Seller.h), l'intestazione definita dall'utente dovrebbe ora essere inclusa, come segue:

#include "Seller.h"

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

Se il file di intestazione è predefinito, devi semplicemente scrivere il nome del file di intestazione tra parentesi angolari e sembrerebbe così (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 header, dovresti scrivere il nome del file header tra virgolette. Supponiamo quindi che tu abbia scritto un file header chiamato myfile.h, quindi questo è un esempio di come useresti la direttiva include per includere quel file:

#include "myfile.h"

2
Non ha nulla a che fare con i file di intestazione predefiniti. Ha a che fare con le posizioni da cercare.
C Johnson,

9

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

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


9
#include <abc.h>

è usato per includere file di libreria standard. Quindi il compilatore verificherà le posizioni in cui risiedono le intestazioni di libreria 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 nelle -Icartelle definite.


7

In C ++, includere 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 d'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.


7

Modulo 1 - #include <xxx>

Innanzitutto, cerca la presenza del file di intestazione nella directory corrente da cui viene invocata la direttiva. Se non lo trova, cerca nell'elenco preconfigurato delle directory di sistema standard.

Modulo 2 - #include "xxx"

Questo cerca la presenza del file header nella directory corrente da cui viene invocata la direttiva.


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

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


Fondamentalmente, il modulo "xxx" non è altro che la ricerca nella directory corrente; se non trovato ricadendo nel modulo


3
Se decidi di rispondere a una domanda precedente con risposte ben definite e corrette, l'aggiunta di una nuova risposta a fine giornata potrebbe non farti ottenere alcun credito. Se hai alcune nuove informazioni distintive, o sei convinto che le altre risposte siano tutte sbagliate, aggiungi sicuramente una nuova risposta, ma "l'ennesima risposta" fornisce le stesse informazioni di base molto tempo dopo che la domanda è stata generalmente vinta " ti guadagno molto credito.
Jonathan Leffler,

1
@Jonathan Leffler Puoi indicarmi la risposta "consolidata" che ritieni sia concisa e precisa come la risposta di Darshan?
personal_cloud

1
La descrizione del #include "header.h"modulo non è accurata, @personal_cloud. Ritengo che la risposta di piCookie e Yann Droneaud sia la più rilevante in quanto identificano la provenienza delle loro informazioni. Non trovo neanche la risposta più votata del tutto soddisfacente.
Jonathan Leffler,

Perché questa risposta è mostrata in alto, mentre due risposte più in basso c'è una più di 650 voti uno? Questa risposta mi ha confuso, perché non corrisponde al comportamento osservato da me. Ciò potrebbe essere dovuto al fatto che l'ultima frase è stata interrotta a causa della mancanza di parentesi angolari. Non sono sicuro di cosa significhi.
Neonit

6

La #include <filename>si usa quando un file di sistema è stato denominato. Questo è un file di intestazione che può essere trovato nelle posizioni predefinite del sistema come /usr/includeo /usr/local/include. Per i tuoi file che devono essere inclusi in un altro programma devi usare la #include "filename"sintassi.


6

il "<nome file>" cerca in posizioni di libreria C standard

mentre "nomefile" cerca anche nella directory corrente.

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


4
Quali nuove informazioni aggiungono questa risposta alle altre?
Daniel Langr,

5

La semplice regola generale è utilizzare parentesi angolate per includere i file di intestazione forniti con il compilatore. Utilizzare le virgolette doppie 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 modo più dettagliato le direttive pre-processore. Se sei un programmatore principiante, quella pagina dovrebbe aiutarti a capire tutto ciò. L'ho imparato da qui e l'ho seguito al lavoro.


4
#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 su preprocessori e intestazione. Leggi C - Preprocessori .


3

#include <filename>

  • Il preprocessore cerca in modo dipendente dall'implementazione. Indica al compilatore di cercare la directory in cui si trovano i file di intestazione del sistema.
  • Questo metodo di solito viene utilizzato per trovare i file di intestazione standard.

#include "filename"

  • Questo dice al compilatore di cercare i file di intestazione in cui il programma è in esecuzione. Se è fallito, si comporta come#include <filename> e cerca quel file di intestazione nel punto in cui sono memorizzati i file di intestazione del sistema.
  • Questo metodo viene solitamente utilizzato per identificare i file di intestazione definiti dall'utente (file di intestazione creati dall'utente). Non utilizzare questo se si desidera chiamare la libreria standard perché richiede più tempo di compilazione di #include <filename>.

2

Per vedere l'ordine di ricerca sul tuo sistema usando gcc, basato sulla 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)
Target: x86_64-apple-darwin18.0.0
Modello discussione: posix InstalledDir: Library / Developer / CommandLineTools / usr / bin
"/ Library / Developer / CommandLineTools / usr / bin / clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-use -Werror = deprecated-objc-isa-use -E -disable-free - disable-llvm-verifier -discard-value-names -main-file-name 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) target predefinito x86_64-apple-darwin18.0.0 ignorando la directory inesistente "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" ignoring inexistent 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
/ Library / Developer / CommandLineTools / usr / include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/ Library / Developer / CommandLineTools / SDKs / MacOSX10.14.sdk / Sistema / Libreria / Frameworks (directory framework)
Fine dell'elenco di ricerca.


1
#include <file> 

Include un file in cui si trova la directory di inclusione predefinita.

#include "file" 

Include un file nella directory corrente in cui è stato compilato.


-2

Esistono due modi per scrivere l'istruzione #include: questi sono:

#include"filename"
#include<filename>

Il significato di ogni forma è

#include"mylib.h"

Questo comando cercherebbe il file mylib.hnella directory corrente e l'elenco specificato delle directory come menzionato nel percorso di ricerca include che potrebbe essere stato impostato.

#include<mylib.h>

Questo comando cercherebbe il file mylib.hsolo nell'elenco di directory specificato.

Il percorso di ricerca include non è altro che un elenco di directory che verrebbero ricercate per il file incluso. Diversi compilatori C consentono di impostare il percorso di ricerca in modi diversi.


1
Se decidi di rispondere a una domanda precedente con risposte ben definite e corrette, l'aggiunta di una nuova risposta a fine giornata potrebbe non farti ottenere alcun credito. Se hai alcune nuove informazioni distintive, o sei convinto che le altre risposte siano tutte sbagliate, aggiungi sicuramente una nuova risposta, ma "l'ennesima risposta" fornisce le stesse informazioni di base molto tempo dopo che la domanda è stata generalmente vinta " ti guadagno molto credito.
Jonathan Leffler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.