Quelle est la différence entre #include <filename> et #include "filename"?


2357

Dans les langages de programmation C et C ++, quelle est la différence entre l'utilisation de crochets angulaires et l'utilisation de guillemets dans une includeinstruction, comme suit?

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



Pour le comportement de Visual Studio, veuillez consulter: docs.microsoft.com/en-us/cpp/preprocessor/…
smwikipedia

Réponses:


1405

En pratique, la différence réside dans l'emplacement où le préprocesseur recherche le fichier inclus.

Pour #include <filename>le préprocesseur recherche de manière dépendante de l'implémentation, normalement dans des répertoires de recherche pré-désignés par le compilateur / IDE. Cette méthode est normalement utilisée pour inclure des fichiers d'en-tête de bibliothèque standard.

Car #include "filename"le préprocesseur recherche d'abord dans le même répertoire que le fichier contenant la directive, puis suit le chemin de recherche utilisé pour le #include <filename>formulaire. Cette méthode est normalement utilisée pour inclure des fichiers d'en-tête définis par le programmeur.

Une description plus complète est disponible dans la documentation GCC sur les chemins de recherche .


135
L'instruction: "le préprocesseur recherche dans le même répertoire ..." peut être vraie dans la pratique mais la norme indique que le fichier source nommé est "recherché d'une manière définie par l'implémentation". Voir la réponse de piCookie.
Richard Corden

60
Bien que votre réponse puisse sembler "vraie", car c'est le nombre d'implémentations qui fonctionnent par convention, vous devriez examiner de près les réponses de aib et de piCookie. Ils soulignent tous les deux (soutenu par le libellé de la norme C) que la véritable distinction est l'inclusion d'un "en-tête" par rapport à l'inclusion d'un "fichier source" (et non, cela ne signifie pas ".h" vs ". c "). Dans ce contexte, le "fichier source" peut être (et est généralement, et devrait presque toujours l'être) un fichier ".h". Un en-tête ne doit pas nécessairement être un fichier (un compilateur pourrait par exemple inclure un en-tête qui est codé statiquement, pas dans un fichier).
Dan Moulding,

5
"... le préprocesseur recherche dans le même répertoire que le fichier en cours de compilation le fichier à inclure." Cette déclaration n'est pas complètement correcte. J'ai été intéressé par cette question parce que j'étais curieux de savoir quelle était la réponse réelle, mais je sais que ce n'est pas vrai car au moins avec gcc lorsque vous spécifiez un chemin d'inclusion supplémentaire avec -I qui recherchera les fichiers spécifiés avec #include "filename. h "
Gabriel Southern

9
Ceux qui n'aiment pas la réponse, s'il vous plaît, donnent un exemple pratique, où c'est faux.
0kcats

1
Effectivement, j'ai récemment mélangé ces syntaxes lors de l'inclusion d'en-têtes de la «même» bibliothèque et je me suis retrouvé avec des erreurs de redéfinition. Si je comprends bien, j'ai #include <...>utilisé le package installé sur le système et #include "..."utilisé la version du référentiel à proximité. Je pourrais les avoir à l'envers. Dans les deux cas, le garde d'inclusion dans l'en-tête empaqueté est préfixé par un trait de soulignement. (Cela pourrait être une convention pour les packages ou peut-être un moyen d'empêcher délibérément de mélanger les deux, bien que les qualificatifs de version auraient plus de sens pour moi.)
John P

714

La seule façon de le savoir est de lire la documentation de votre implémentation.

Dans la norme C , section 6.10.2, les paragraphes 2 à 4 stipulent:

  • Une directive de prétraitement du formulaire

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

    recherche une séquence de lieux définis par l' implémentation pour trouver un en- tête identifié de façon unique par la séquence spécifiée entre le <et >délimiteurs, et provoque le remplacement de cette directive par le contenu de l' en- tête . La façon dont les emplacements sont spécifiés ou l'en-tête identifié est définie par l'implémentation.

  • Une directive de prétraitement du formulaire

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

    provoque le remplacement de cette directive par l'ensemble du contenu du fichier source identifié par la séquence spécifiée entre les "délimiteurs. Le fichier source nommé est recherché d'une manière définie par l'implémentation. Si cette recherche n'est pas prise en charge, ou si la recherche échoue, la directive est retraitée comme si elle se lisait

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

    avec la séquence contenue identique (y compris les >caractères, le cas échéant) de la directive d'origine.

  • Une directive de prétraitement du formulaire

    #include pp-tokens new-line

    (qui ne correspond pas à l'une des deux formes précédentes) est autorisée. Les jetons de prétraitement suivants includedans la directive sont traités comme dans le texte normal. (Chaque identificateur actuellement défini comme un nom de macro est remplacé par sa liste de remplacement de jetons de prétraitement.) La directive résultant après tous les remplacements doit correspondre à l'un des deux formulaires précédents. La méthode par laquelle une séquence de jetons de prétraitement entre une <et une >paire de jetons de prétraitement ou une paire de "caractères est combinée en un seul jeton de prétraitement de nom d'en-tête est définie par l'implémentation.

Définitions:

  • h-char: tout membre du jeu de caractères source à l'exception du caractère de nouvelle ligne et >

  • q-char: tout membre du jeu de caractères source à l'exception du caractère de nouvelle ligne et "


108
Pertinent: implémentation en g ++ et en visual c ++
Alexander Malakhov

27
@piCookie <filename> et "filename" recherchent tous les deux des emplacements définis par l'implémentation. Alors, quelle est la difference ?
onmyway133

15
@Stefan, je ne fais que citer la norme qui ne dit rien sur INCLUDE_PATH. Votre implémentation peut le faire et la mienne non. La question d'origine était génériquement C et pas spécifiquement gcc (qui je ne pense pas utilise INCLUDE_PATH) ou Microsoft C (ce que je pense fait) ou tout autre, donc il ne peut pas être répondu de manière générique mais à la place, la documentation de chaque implémentation doit être référencée.
piCookie

12
Comme pour toutes ces situations, des exemples concrets (en particulier de scénarios courants) sont très utiles et également appréciés. Les réponses génériques inutilement obtus n'ont pas autant d'utilité pratique.
vargonian

132
"Voici comment la norme C peut être verbeuse et ne pas répondre à votre question"
anatolyg

287

La séquence de caractères entre <et> fait uniquement référence à un en-tête, qui n'est pas nécessairement un fichier. Les implémentations sont à peu près libres d'utiliser la séquence de caractères comme elles le souhaitent. (Généralement, cependant, il suffit de le traiter comme un nom de fichier et de faire une recherche dans le chemin d'inclusion , comme l'indiquent les autres articles.)

Si le #include "file"formulaire est utilisé, l'implémentation recherche d'abord un fichier du nom donné, s'il est pris en charge. Sinon (pris en charge) ou si la recherche échoue, l'implémentation se comporte comme si l'autre #include <file>formulaire ( ) était utilisé.

En outre, un troisième formulaire existe et est utilisé lorsque la #includedirective ne correspond à aucun des formulaires ci-dessus. Sous cette forme, un prétraitement de base (tel qu'une expansion de macro) est effectué sur les "opérandes" de la #includedirective, et le résultat devrait correspondre à l'une des deux autres formes.


50
+1, c'est probablement la réponse la plus concise et la plus correcte ici. Selon la norme (citée par piCookie dans sa réponse), la seule vraie différence est "en-tête" contre "fichier source". Le mécanisme de recherche est défini dans l'implémentation de toute façon. L'utilisation de guillemets doubles signifie que vous avez l'intention d'inclure un "fichier source", tandis que les crochets angulaires signifient que vous avez l'intention d'inclure un "en-tête" qui, comme vous le dites, peut ne pas être du tout un fichier.
Dan Moulding

3
Voir le commentaire de Dan Moulding sur la réponse de quest49; les en-têtes standard n'ont pas besoin d'être sous forme de fichier, ils peuvent être intégrés.
2011 à 9h28

10
J'ai lu ceci "les en-têtes standard n'ont pas besoin d'être sous forme de fichier" depuis une décennie. Voulez-vous donner un exemple concret?
Maxim Egorushkin

12
@ Maxim Yegorushkin: Je ne peux pas non plus penser à des exemples réels; cependant, aucun compilateur C11 complet ne peut exister pour MS-DOS à moins que les en-têtes n'aient pas à être des fichiers. Cela est dû au fait que certains des noms d'en-tête C11 ne sont pas compatibles avec la limitation de nom de fichier MS-DOS "8.3".
Dan Moulding du

18
@MaximEgorushkin: Le compilateur VAX / VMS C a conservé tous les en-têtes de bibliothèque d'exécution C dans un seul fichier de bibliothèque textuelle (similaire à une archive Unix), et a utilisé la chaîne entre le <et >comme clé pour indexer dans la bibliothèque.
Adrian McCarthy

117

Quelques bonnes réponses font ici référence au standard C mais ont oublié le standard POSIX, en particulier le comportement spécifique de la commande c99 (par exemple le compilateur C) .

Selon The Open Group Base Specifications Issue 7 ,

-I répertoire

Modifiez l'algorithme de recherche des en-têtes dont les noms ne sont pas des chemins d'accès absolus à rechercher dans le répertoire nommé par le chemin d'accès du répertoire avant de rechercher aux endroits habituels. Ainsi, les en-têtes dont les noms sont placés entre guillemets doubles ("") doivent être recherchés d'abord dans le répertoire du fichier avec la ligne #include , puis dans les répertoires nommés dans les options -I , et enfin aux endroits habituels. Pour les en-têtes dont les noms sont placés entre crochets ("<>"), l'en-tête doit être recherché uniquement dans les répertoires nommés dans les options -I , puis aux endroits habituels. Les répertoires nommés dans les options -I doivent être recherchés dans l'ordre spécifié.Appel de la commande c99 .

Donc, dans un environnement compatible POSIX, avec un compilateur C compatible POSIX, #include "file.h"va probablement chercher en ./file.hpremier, où .est le répertoire où se trouve le fichier avec l' #includeinstruction, tandis que #include <file.h>, va probablement chercher en /usr/include/file.hpremier, où /usr/includeest votre système défini emplacements habituels pour les en-têtes (il ne semble pas défini par POSIX).


1
Quelle est la source exacte du texte? Est-ce de la partie normative de l'IEEE Std 1003.1, 2013?
osgx

7
@osgx: cette formulation (ou quelque chose d'extrêmement similaire) se trouve dans la spécification POSIX pour c99- qui est le nom POSIX du compilateur C. (La norme POSIX 2008 pouvait difficilement faire référence à C11; la mise à jour 2013 de POSIX 2008 n'a pas changé la norme C à laquelle elle faisait référence.)
Jonathan Leffler

1
C'était aussi ma première pensée. La page de manuel de gcc inclut cela comme les autres. Il y a aussi une chose similaire pour les bibliothèques - -L.
Pryftan

50

La documentation de GCC indique ce qui suit sur la différence entre les deux:

Les fichiers d'en-tête utilisateur et système sont inclus à l'aide de la directive de prétraitement ‘#include’. Il a deux variantes:

#include <file>

Cette variante est utilisée pour les fichiers d'en-tête système. Il recherche un fichier nommé fichier dans une liste standard de répertoires système. Vous pouvez ajouter des répertoires à cette liste avec l' -Ioption (voir Invocation ).

#include "file"

Cette variante est utilisée pour les fichiers d'en-tête de votre propre programme. Il recherche un fichier nommé fichier d'abord dans le répertoire contenant le fichier actuel, puis dans les répertoires de devis et ensuite les mêmes répertoires que ceux utilisés <file>. Vous pouvez ajouter des répertoires à la liste des répertoires de devis avec l' -iquoteoption. L'argument de ‘#include’, qu'il soit délimité par des guillemets ou des crochets, se comporte comme une constante de chaîne dans la mesure où les commentaires ne sont pas reconnus et les noms de macro ne sont pas développés. Ainsi, #include <x/*y>spécifie l'inclusion d'un fichier d'en-tête système nommé x/*y.

Cependant, si des barres obliques inverses se produisent dans le fichier, elles sont considérées comme des caractères de texte ordinaires et non comme des caractères d'échappement. Aucune des séquences d'échappement de caractères appropriées aux constantes de chaîne en C n'est traitée. Ainsi, #include "x\n\\y"spécifie un nom de fichier contenant trois barres obliques inverses. (Certains systèmes interprètent «\» comme un séparateur de chemin d'accès. Tous ces éléments interprètent également de ‘/’la même manière. Il est plus portable à utiliser uniquement ‘/’.)

C'est une erreur s'il y a quelque chose (autre que des commentaires) sur la ligne après le nom du fichier.


46

Cela fait:

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

avec .soit le répertoire du fichier où le#include est contenu, et / ou le répertoire de travail actuel du compilateur, et / oudefault_include_paths

et

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

Si ./c'est le cas <default_include_paths>, cela ne fait aucune différence.

Si se mypath/myfiletrouve dans un autre répertoire d'inclusion, le comportement n'est pas défini.


12
Non, #include "mypath/myfile"n'est pas équivalent à #include "./mypath/myfile". Comme le dit la réponse de piCookie, les guillemets doubles indiquent au compilateur de rechercher d'une manière définie par l'implémentation - ce qui inclut la recherche aux endroits spécifiés #include <...>. (En fait, c'est probablement équivalent, mais seulement parce que, par exemple, /usr/include/mypath/myfileon peut l'appeler /usr/include/./mypath/myfile- au moins sur les systèmes de type Unix.)
Keith Thompson

1
@Keith Thompson: C'est vrai, je pensais à ma boîte Linux. Évidemment, cela pourrait être différent. Bien qu'en pratique, Windows en tant que système d'exploitation non-Posix interprète également / comme séparateur de chemin, et ./ existe également.
Stefan Steiger

1
l' option -L dirpath ajoute ensuite dirpath au defaultincludepaths, au lieu de donner une autre signification au .(comme mentionné ci-dessus). Cela a la conséquence attendue que les deux #include "..."et la #include <...>recherche dans dirpath
Protongun

1
Je pense que cette réponse est incorrecte, car elle implique que les en-têtes inclus avec des guillemets doubles sont toujours recherchés dans le répertoire de travail actuel. Le mécanisme de recherche est beaucoup plus détaillé; cette réponse est incomplète. Je n'ajoute pas ce commentaire pour me plaindre ou pleurnicher, mais parce que le système me demande d'ajouter un commentaire pour expliquer pourquoi j'ai voté contre cette réponse.
Carlo Wood

39

L' <file>inclure indique le préprocesseur de rechercher dans les -Irépertoires et dans des répertoires prédéfinis d' abord , puis dans le répertoire du fichier .c. L' "file"inclure indique le préprocesseur pour rechercher le répertoire du fichier source première , puis revenir à -Iet prédéfini. Toutes les destinations sont recherchées de toute façon, seul l'ordre de recherche est différent.

La norme 2011 traite principalement des fichiers inclus dans "16.2 Inclusion de fichiers source".

2 Une directive de prétraitement du formulaire

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

recherche une séquence d'emplacements définis par l'implémentation pour un en-tête identifié uniquement par la séquence spécifiée entre les délimiteurs <et>, et provoque le remplacement de cette directive par le contenu entier de l'en-tête. La façon dont les emplacements sont spécifiés ou l'en-tête identifié est définie par l'implémentation.

3 Une directive de prétraitement du formulaire

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

entraîne le remplacement de cette directive par le contenu entier du fichier source identifié par la séquence spécifiée entre les "délimiteurs". Le fichier source nommé est recherché d'une manière définie par l'implémentation. Si cette recherche n'est pas prise en charge, ou si la recherche échoue , la directive est retraitée comme si elle se lisait

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

avec la séquence contenue identique (y compris> caractères, le cas échéant) de la directive d'origine.

Notez que le "xxx"formulaire se dégrade en <xxx>formulaire si le fichier est introuvable. Le reste est défini par l'implémentation.


4
Pourriez-vous indiquer où, dans la norme C, cette -Iactivité est spécifiée?
juanchopanza

1
Je ne vois aucune référence à -I.
juanchopanza

2
C'est la partie "définie par l'implémentation".

28

#include <file.h>indique au compilateur de rechercher l'en-tête dans son répertoire "includes", par exemple pour MinGW, le compilateur rechercherait file.hdans C: \ MinGW \ include \ ou partout où votre compilateur est installé.

#include "file"indique au compilateur de rechercher le répertoire courant (c'est-à-dire le répertoire dans lequel réside le fichier source) file.

Vous pouvez utiliser l' -Iindicateur pour GCC pour lui indiquer que, lorsqu'il rencontre une inclusion avec des crochets angulaires, il doit également rechercher les en-têtes dans le répertoire après -I. GCC traitera le répertoire après l'indicateur comme s'il s'agissait du includesrépertoire.

Par exemple, si vous avez un fichier appelé myheader.hdans votre propre répertoire, vous pouvez dire #include <myheader.h>si vous avez appelé GCC avec l'indicateur -I .(indiquant qu'il doit rechercher les inclusions dans le répertoire actuel.)

Sans l' -Iindicateur, vous devrez utiliser #include "myheader.h"pour inclure le fichier ou vous déplacer myheader.hvers le includerépertoire de votre compilateur.


22

Selon la norme - oui, ils sont différents:

  • Une directive de prétraitement du formulaire

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

    recherche une séquence de lieux définis par l' implémentation pour trouver un en- tête identifié de façon unique par la séquence spécifiée entre le <et >délimiteurs, et provoque le remplacement de cette directive par le contenu de l' en- tête. La façon dont les emplacements sont spécifiés ou l'en-tête identifié est définie par l'implémentation.

  • Une directive de prétraitement du formulaire

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

    provoque le remplacement de cette directive par le contenu entier du fichier source identifié par la séquence spécifiée entre les "délimiteurs. Le fichier source nommé est recherché d'une manière définie par l'implémentation. Si cette recherche n'est pas prise en charge, ou si la recherche échoue, la directive est retraitée comme si elle se lisait

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

    avec la séquence contenue identique (y compris les >caractères, le cas échéant) de la directive d'origine.

  • Une directive de prétraitement du formulaire

    #include pp-tokens new-line

    (qui ne correspond pas à l'une des deux formes précédentes) est autorisée. Les jetons de prétraitement suivants includedans la directive sont traités comme dans le texte normal. (Chaque identificateur actuellement défini comme un nom de macro est remplacé par sa liste de remplacement de jetons de prétraitement.) La directive résultant après tous les remplacements doit correspondre à l'un des deux formulaires précédents. La méthode par laquelle une séquence de jetons de prétraitement entre une <et une >paire de jetons de prétraitement ou une paire de "caractères est combinée en un seul jeton de prétraitement de nom d'en-tête est définie par l'implémentation.

Définitions:

  • h-char: tout membre du jeu de caractères source à l'exception du caractère de nouvelle ligne et >

  • q-char: tout membre du jeu de caractères source à l'exception du caractère de nouvelle ligne et "

Notez que la norme ne dit aucune relation entre les manières définies par l'implémentation. Le premier formulaire recherche d'une manière définie par l'implémentation, et l'autre d'une manière (éventuellement autre) définie par l'implémentation. La norme spécifie également que certains fichiers include doivent être présents (par exemple, <stdio.h>).

Formellement, vous devrez lire le manuel de votre compilateur, mais normalement (par tradition) le #include "..."formulaire recherche le répertoire du fichier dans lequel le a #includeété trouvé en premier, puis les répertoires que le #include <...>formulaire recherche (le chemin d'inclusion, par exemple les en-têtes du système) ).


2
Il s'agit principalement du même texte que la réponse de piCookie de sept ans plus tôt.
Kyle Strand

5
@KyleStrand C'est parce que le même texte est une citation de la section pertinente de la norme - ce texte doit être identique. La réponse réelle n'est pas le même texte et est quelque peu différente - bien que je reconnaisse également que cela sera écrit dans la documentation de la mise en œuvre, je note également qu'il existe également une manière traditionnelle d'interpréter ces principes (que la plupart ou tous les compilateurs que j'ai utilisés respectent) .
skyking

2
OMI, c'est la meilleure réponse ici, car elle couvre à la fois ce que dit la norme et ce que la plupart des compilateurs font réellement.
plugwash

17

Merci pour les bonnes réponses, esp. Adam Stelmaszczyk et piCookie, et aib.

Comme de nombreux programmeurs, j'ai utilisé la convention informelle d'utiliser le "myApp.hpp"formulaire pour les fichiers spécifiques à l'application et le <libHeader.hpp>formulaire pour les fichiers système de bibliothèque et de compilateur, c'est-à-dire les fichiers spécifiés dans /Iet la INCLUDEvariable d'environnement, pendant des années en pensant que c'était la norme.

Cependant, la norme C indique que l'ordre de recherche est spécifique à l'implémentation, ce qui peut compliquer la portabilité. Pour aggraver les choses, nous utilisons la confiture, qui détermine automatiquement où se trouvent les fichiers d'inclusion. Vous pouvez utiliser des chemins relatifs ou absolus pour vos fichiers d'inclusion. c'est à dire

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

Les anciennes versions de MSVS nécessitaient des doubles barres obliques inverses (\\), mais maintenant ce n'est plus nécessaire. Je ne sais pas quand ça a changé. Utilisez simplement des barres obliques pour la compatibilité avec 'nix (Windows l'acceptera).

Si vous êtes vraiment inquiet à ce sujet, utilisez "./myHeader.h"un fichier include dans le même répertoire que le code source (mon projet actuel très volumineux a des noms de fichiers include en double dispersés - vraiment un problème de gestion de la configuration).

Voici l' explication MSDN copiée ici pour votre commodité).

Formulaire cité

Le préprocesseur recherche les fichiers d'inclusion dans cet ordre:

  1. Dans le même répertoire que le fichier contenant l'instruction #include.
  2. Dans les répertoires des fichiers inclus actuellement ouverts, dans l'ordre inverse de
    leur ouverture. La recherche commence dans le répertoire du fichier d'inclusion parent et se
    poursuit vers le haut dans les répertoires de tout fichier d'inclusion de grand-parent.
  3. Le long du chemin spécifié par chaque /Ioption du compilateur.
  4. Le long des chemins qui sont spécifiés par la INCLUDEvariable d'environnement.

Forme de support d'angle

Le préprocesseur recherche les fichiers d'inclusion dans cet ordre:

  1. Le long du chemin spécifié par chaque /Ioption du compilateur.
  2. Lorsque la compilation se produit sur la ligne de commande, le long des chemins spécifiés par la INCLUDEvariable d'environnement.

16

Au moins pour la version GCC <= 3.0, la forme équerre ne génère pas de dépendance entre le fichier inclus et le fichier inclus.

Donc si vous voulez générer des règles de dépendance (en utilisant l'option GCC -M par exemple), vous devez utiliser le formulaire entre guillemets pour les fichiers qui doivent être inclus dans l'arbre de dépendance.

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


1
Oui - il existe plusieurs façons de générer des dépendances. C'est l'un d'eux mais ce n'est pas le seul.
Pryftan

15

Un #include ""compilateur recherche normalement le dossier du fichier qui contient cette inclusion, puis les autres dossiers. Pour #include <>le compilateur ne recherche pas le dossier du fichier actuel.


1
Je ne sais pas pourquoi les gens ne sont pas d'accord.
Maxim Egorushkin

Je suppose que c'est parce que la plupart des gens ne compilent que les fichiers dans leur CWD. Si vous êtes dans le répertoire foo et que vous compilez foo / unittest / bar.c, et qu'il inclut bar.h, alors "bar.h" fonctionne et <bar.h> ne fonctionne pas.

1
Les gens @Maxim sont en désaccord parce que le comportement que vous décrivez n'est pas standard C.
osvein

2
@Spookbuster À droite, la norme dit les deux <filename>et "filename"recherche des endroits définis par l'implémentation.
Maxim Egorushkin

14

Lorsque vous utilisez #include <nomfichier>, le préprocesseur recherche le fichier dans le répertoire des fichiers d'en-tête C \ C ++ (stdio.h \ cstdio, chaîne, vecteur, etc.). Mais, lorsque vous utilisez #include "filename": d'abord, le préprocesseur recherche le fichier dans le répertoire courant, et s'il ne le fait pas ici - il le recherche dans le répertoire des fichiers d'en-tête C \ C ++.


1
Après qu'une réponse parfaite ait été disponible pendant des années, pourquoi en soumettre une, c'est tout simplement faux? Même si elle est courante, la #includedirective n'est pas du tout strictement liée aux fichiers.
IInspectable

@IInspectable, veuillez expliquer pourquoi ce n'est pas du tout lié aux fichiers.
Behrooz Karjoo

11

Un #include avec des crochets cherchera une "liste d'emplacements dépendants de l'implémentation" (ce qui est une manière très compliquée de dire "en-têtes système") pour le fichier à inclure.

Un #include avec des guillemets cherchera simplement un fichier (et, "d'une manière dépendante de l'implémentation", bleh). Ce qui signifie qu'en anglais normal, il essaiera d'appliquer le chemin / nom de fichier que vous lui lancez et ne ajoutera pas de chemin système ou ne le modifiera pas autrement.

De plus, si #include "" échoue, il est relu comme #include <> par la norme.

La documentation de gcc a une description (spécifique au compilateur) qui, bien qu'elle soit spécifique à gcc et non à la norme, est beaucoup plus facile à comprendre que le discours de style avocat des normes ISO.


Cependant, l'utilisation de crochets ou de guillemets n'affecte pas la façon dont les fichiers sont inclus, c'est exactement la même chose: le préprocesseur crée essentiellement un gros fichier source en copiant et en diffusant le code des fichiers inclus dans le fichier source d'origine, avant de donner au compilateur (le préprocesseur fait autre chose, comme #define sustitution, #if evaluation, etc. mais le traitement #include est aussi simple que cela)
Loghorn

Et les conflits? Par exemple, disons que j'ai zlib.hdans mes chemins de recherche "utilisateur", et qu'une version différente existe dans le chemin de recherche du système, alors #include <zlib.h>inclut la version du système et #include "zlib.h"la mienne?
the_mandrill

Aha, a répondu à ma propre question: stackoverflow.com/questions/21593/…
the_mandrill

Merci d'avoir reconnu que les normes et les conventions de mise en œuvre typiques sont toutes deux pertinentes ici, plutôt que de simplement déclarer qu'elles ne sont pas reconnaissables car elles ne sont pas spécifiées par la norme.
Kyle Strand

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

Exemple:

Le nom de fichier ici est 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

Dans l'implémentation de classe (par exemple, Seller.cppet dans d'autres fichiers qui utiliseront le fichier Seller.h), l'en-tête défini par l'utilisateur doit maintenant être inclus, comme suit:

#include "Seller.h"

10
  • #include <> est pour les fichiers d'en-tête prédéfinis

Si le fichier d'en-tête est prédéfini, vous écririez simplement le nom du fichier d'en-tête entre crochets angulaires, et cela ressemblerait à ceci (en supposant que nous avons un nom de fichier d'en-tête prédéfini iostream):

#include <iostream>
  • #include " " est pour les fichiers d'en-tête que le programmeur définit

Si vous (le programmeur) avez écrit votre propre fichier d'en-tête, vous écririez le nom du fichier d'en-tête entre guillemets. Supposons donc que vous ayez écrit un fichier d'en-tête appelé myfile.h, alors voici un exemple de la façon dont vous utiliseriez la directive include pour inclure ce fichier:

#include "myfile.h"

2
Cela n'a rien à voir avec des fichiers d'en-tête prédéfinis. Cela concerne les emplacements à rechercher.
C Johnson

9

De nombreuses réponses se concentrent ici sur les chemins que le compilateur recherchera afin de trouver le fichier. Bien que ce soit ce que font la plupart des compilateurs, un compilateur conforme est autorisé à être préprogrammé avec les effets des en-têtes standard, et à le traiter, par exemple, #include <list>comme un commutateur, et il n'a pas besoin d'exister en tant que fichier.

Ce n'est pas purement hypothétique. Il existe au moins un compilateur qui fonctionne de cette façon. L'utilisation #include <xxx>uniquement avec des en-têtes standard est recommandée.


9
#include <abc.h>

est utilisé pour inclure des fichiers de bibliothèque standard. Ainsi, le compilateur vérifiera les emplacements où résident les en-têtes de bibliothèque standard.

#include "xyz.h"

indiquera au compilateur d'inclure les fichiers d'en-tête définis par l'utilisateur. Ainsi, le compilateur vérifiera ces fichiers d'en-tête dans le dossier actuel ou les -Idossiers définis.


7

En C ++, incluez un fichier de deux manières:

Le premier est #include qui indique au préprocesseur de rechercher le fichier à l'emplacement par défaut prédéfini. Cet emplacement est souvent une variable d'environnement INCLUDE qui indique le chemin d'accès pour inclure les fichiers.

Et le deuxième type est #include "filename" qui indique au préprocesseur de rechercher d'abord le fichier dans le répertoire courant, puis de le rechercher dans les emplacements prédéfinis que l'utilisateur a configurés.


7

Formulaire 1 - #inclut <xxx>

Tout d'abord, recherche la présence du fichier d'en-tête dans le répertoire courant à partir duquel la directive est invoquée. S'il n'est pas trouvé, il recherche dans la liste préconfigurée des répertoires système standard.

Formulaire 2 - # inclure "xxx"

Cela recherche la présence du fichier d'en-tête dans le répertoire courant d'où la directive est invoquée.


La liste exacte des répertoires de recherche dépend du système cible, de la configuration de GCC et de l'endroit où il est installé. Vous pouvez trouver la liste des répertoires de recherche de votre compilateur GCC en l'exécutant avec l'option -v.

Vous pouvez ajouter des répertoires supplémentaires au chemin de recherche en utilisant - I dir , ce qui entraîne la recherche de dir après le répertoire en cours (pour le formulaire de citation de la directive) et avant les répertoires système standard.


Fondamentalement, le formulaire "xxx" n'est rien d'autre qu'une recherche dans le répertoire courant; sinon trouvé retomber le formulaire


3
Si vous décidez de répondre à une question plus ancienne qui a des réponses bien établies et correctes, l'ajout d'une nouvelle réponse en fin de journée peut ne pas vous valoir de crédit. Si vous avez de nouvelles informations distinctives, ou si vous êtes convaincu que les autres réponses sont toutes fausses, ajoutez certainement une nouvelle réponse, mais `` encore une autre réponse '' donnant les mêmes informations de base longtemps après que la question a été posée est généralement gagnée '' t vous gagner beaucoup de crédit.
Jonathan Leffler

1
@Jonathan Leffler Pouvez-vous m'indiquer la réponse "bien établie" qui vous semble aussi concise et exacte que la réponse de Darshan?
personal_cloud

1
La description du #include "header.h"formulaire n'est pas exacte, @personal_cloud. Je considère que la réponse de piCookie et Yann Droneaud est la plus pertinente car ils identifient la provenance de leurs informations. Je ne trouve pas non plus la réponse la plus votée entièrement satisfaisante.
Jonathan Leffler

Pourquoi cette réponse est-elle affichée en haut, alors que deux réponses plus bas, il y en a une de plus de 650 votes? Cette réponse m'a confondu, car elle ne correspond pas au comportement observé par moi. Cela peut être dû au fait que la dernière phrase est interrompue car les parenthèses angulaires ne s'échappent pas. Je ne sais pas ce que cela est censé signifier.
Neonit

6

Le #include <filename>est utilisé lorsqu'un fichier système est référencé. Il s'agit d'un fichier d'en-tête qui peut être trouvé aux emplacements par défaut du système comme /usr/includeou /usr/local/include. Pour vos propres fichiers qui doivent être inclus dans un autre programme, vous devez utiliser la #include "filename"syntaxe.


6

les recherches "<nom de fichier>" dans les emplacements de bibliothèque C standard

tandis que "nom de fichier" recherche également dans le répertoire courant.

Idéalement, vous utiliseriez <...> pour les bibliothèques C standard et "..." pour les bibliothèques que vous écrivez et qui sont présentes dans le répertoire courant.


4
Quelles nouvelles informations ajoutent cette réponse aux autres?
Daniel Langr

5

La règle générale simple consiste à utiliser des crochets inclinés pour inclure les fichiers d'en-tête fournis avec le compilateur. Utilisez des guillemets doubles pour inclure tout autre fichier d'en-tête. La plupart des compilateurs le font de cette façon.

1.9 - Les fichiers d'en-tête expliquent plus en détail les directives de pré-processeur. Si vous êtes un programmeur débutant, cette page devrait vous aider à comprendre tout cela. Je l'ai appris d'ici et je l'ai suivi au travail.


4
#include <filename>

est utilisé lorsque vous souhaitez utiliser le fichier d'en-tête du système C / C ++ ou des bibliothèques du compilateur. Ces bibliothèques peuvent être stdio.h, string.h, math.h, etc.

#include "path-to-file/filename"

est utilisé lorsque vous souhaitez utiliser votre propre fichier d'en-tête personnalisé qui se trouve dans votre dossier de projet ou ailleurs.

Pour plus d'informations sur les préprocesseurs et l'en-tête. Lisez C - Préprocesseurs .


3

#include <filename>

  • Le préprocesseur recherche en fonction de l'implémentation. Il indique au compilateur de rechercher dans le répertoire où se trouvent les fichiers d'en-tête du système.
  • Cette méthode utilise généralement pour rechercher des fichiers d'en-tête standard.

#include "filename"

  • Cela indique au compilateur de rechercher les fichiers d'en-tête où le programme est en cours d'exécution. S'il a échoué, il se comporte comme#include <filename> et recherche ce fichier d'en-tête à l'endroit où les fichiers d'en-tête du système sont stockés.
  • Cette méthode est généralement utilisée pour identifier les fichiers d'en-tête définis par l'utilisateur (fichiers d'en-tête créés par l'utilisateur). Là pour ne pas utiliser ceci si vous voulez appeler la bibliothèque standard car cela prend plus de temps de compilation que #include <filename>.

2

Pour voir l'ordre de recherche sur votre système à l'aide de gcc, en fonction de la configuration actuelle, vous pouvez exécuter la commande suivante. Vous pouvez trouver plus de détails sur cette commande ici

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

Apple LLVM version 10.0.0 (clang-1000.10.44.2)
Cible: x86_64-apple-darwin18.0.0
Modèle de thread: posix InstalledDir: Library / Developer / CommandLineTools / usr / bin
"/ Library / Developer / 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-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 version 10.0.0 (clang-1000.10.44.2) cible par défaut x86_64-apple-darwin18.0.0 ignorant le répertoire inexistant "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" ignorant inexistant répertoire "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." la recherche commence ici:
#include <...> la recherche commence ici:
/ usr / local / include
/ Library / Developer / 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 / System / Library / Frameworks (répertoire framework)
Fin de la liste de recherche.


1
#include <file> 

Inclut un fichier où se trouve le répertoire d'inclusion par défaut.

#include "file" 

Inclut un fichier dans le répertoire courant dans lequel il a été compilé.


-2

Il existe deux façons d'écrire une instruction #include, à savoir:

#include"filename"
#include<filename>

La signification de chaque forme est

#include"mylib.h"

Cette commande rechercherait le fichier mylib.hdans le répertoire courant ainsi que la liste de répertoires spécifiée comme mentionné dans le chemin de recherche d'inclusion qui aurait pu être configuré.

#include<mylib.h>

Cette commande rechercherait le fichier mylib.hdans la liste de répertoires spécifiée uniquement.

Le chemin de recherche inclus n'est rien d'autre qu'une liste de répertoires qui seraient recherchés pour le fichier inclus. Différents compilateurs C vous permettent de définir le chemin de recherche de différentes manières.


1
Si vous décidez de répondre à une question plus ancienne qui a des réponses bien établies et correctes, l'ajout d'une nouvelle réponse en fin de journée peut ne pas vous valoir de crédit. Si vous avez de nouvelles informations distinctives, ou si vous êtes convaincu que les autres réponses sont toutes fausses, ajoutez certainement une nouvelle réponse, mais `` encore une autre réponse '' donnant les mêmes informations de base longtemps après que la question a été posée est généralement gagnée '' t vous gagner beaucoup de crédit.
Jonathan Leffler
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.