Vraag Wat is het verschil tussen #include en #include "filename"?


In de programmeertalen C en C ++, wat is het verschil tussen het gebruik van punthaken en het gebruik van aanhalingstekens in een include verklaring, als volgt?

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

1809
2017-08-22 01:40


oorsprong


antwoorden:


In de praktijk ligt het verschil in de locatie waar de preprocessor naar het opgenomen bestand zoekt.

Voor #include <filename> de preprocessor zoekt op een implementatieafhankelijke manier, normaal in zoekmappen die vooraf zijn aangewezen door de compiler / IDE. Deze methode wordt normaal gesproken gebruikt om standaard bibliotheek header-bestanden op te nemen.

Voor #include "filename" de preprocessor doorzoekt eerst in dezelfde map als het bestand dat de instructie bevat en volgt vervolgens het zoekpad dat voor de #include <filename> het formulier. Deze methode wordt normaal gesproken gebruikt om door de programmeur gedefinieerde header-bestanden op te nemen.

Een meer volledige beschrijving is beschikbaar in de GCC documentatie over zoekpaden.


1045
2017-08-22 01:40



De enige manier om dit te weten, is door de documentatie van uw implementatie te lezen.

In de C-standaard, paragraaf 6.10.2, paragrafen 2 t / m 4 stellen:

  • Een voorbewerkingsrichtlijn van het formulier

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

    doorzoekt een reeks met implementatie gedefinieerde plaatsen voor een header die uniek is geïdentificeerd door de opgegeven reeks tussen de < en > scheidingstekens en zorgt ervoor dat die richtlijn door de volledige inhoud van de kop wordt vervangen. Hoe de plaatsen worden gespecificeerd of de header die wordt geïdentificeerd, is door de implementatie gedefinieerd.

  • Een voorbewerkingsrichtlijn van het formulier

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

    veroorzaakt de vervanging van die richtlijn door de volledige inhoud van het bronbestand geïdentificeerd door de opgegeven reeks tussen de " scheidingstekens. Het genoemde bronbestand wordt op een door de implementatie gedefinieerde manier gezocht. Als deze zoekopdracht niet wordt ondersteund of als het zoeken mislukt, wordt de richtlijn opnieuw verwerkt alsof deze zou kunnen worden gelezen

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

    met de identieke ingesloten reeks (inclusief > tekens, indien aanwezig) van het origineel   richtlijn.

  • Een voorbewerkingsrichtlijn van het formulier

    #include pp-tokens new-line
    

    (dat komt niet overeen met een van de twee voorgaande formulieren) is toegestaan. De preprocessing tokens after include in de richtlijn worden net als in normale tekst verwerkt. (Elke ID die momenteel is gedefinieerd als een macronaam wordt vervangen door de vervangende lijst van voorbewerkingstokens.) De richtlijn die na alle vervangingen ontstaat, moet overeenkomen met een van de twee voorgaande formulieren. De methode waarmee een reeks voorbewerkingstokens tussen a < en een > preprocessing token pair of een paar " tekens worden gecombineerd in een enkele headernaam preprocessing token is door de implementatie gedefinieerd.

Definities:

  • h-char: elk lid van de bronsetset, behalve het teken van de nieuwe regel en >

  • q-char: elk lid van de bronsetset met uitzondering van het karakter van de nieuwe regel en "


594
2017-09-16 21:06



De reeks tekens tussen <en> verwijst op unieke wijze naar een koptekst, die niet noodzakelijk een bestand is. Implementaties zijn vrijwel vrij om de tekenreeks te gebruiken zoals ze willen. (Maar behandel het meestal gewoon als een bestandsnaam en zoek in de neem pad op, zoals de andere berichten vermelden.)

Als het #include "file" formulier wordt gebruikt, zoekt de implementatie eerst naar een bestand met de opgegeven naam, indien dit wordt ondersteund. Indien niet (ondersteund), of als de zoekopdracht mislukt, gedraagt ​​de implementatie zich als de andere (#include <file>) vorm werd gebruikt.

Er bestaat ook een derde formulier dat wordt gebruikt wanneer het #include richtlijn komt niet overeen met een van de bovenstaande formulieren. In deze vorm wordt enige basisvoorbewerking (zoals macro-uitbreiding) uitgevoerd op de "operands" van de #include richtlijn en het resultaat zal naar verwachting overeenkomen met een van de twee andere vormen.


214
2017-09-08 17:43



Enkele goede antwoorden hier verwijzen naar de C-standaard, maar zijn de POSIX-standaard vergeten, vooral het specifieke gedrag van de c99 (bijvoorbeeld C-compiler) opdracht.

Volgens De Open Group Basisspecificaties Uitgave 7,

-IK  directory

Wijzig het algoritme voor het zoeken naar koppen waarvan de naam geen absolute padnamen is om te zoeken in de map met de naam directory padnaam voordat je op de gebruikelijke plaatsen kijkt. Dus headers wiens namen tussen dubbele aanhalingstekens ("") staan, moeten eerst worden gezocht in de map van het bestand met de #include regel, dan in mappen met de naam in -IK opties en als laatste op de gebruikelijke plaatsen. Voor koppen waarvan de naam is ingesloten tussen punthaken ("<>"), wordt de kop alleen gezocht in mappen die zijn genoemd in -IK opties en vervolgens op de gebruikelijke plaatsen. Directories genoemd in -IK de opties zullen in de gespecificeerde volgorde worden doorzocht. Implementaties ondersteunen ten minste tien voorbeelden van deze optie in één exemplaar c99 opdracht aanroep.

Dus in een POSIX-compatibele omgeving, met een POSIX compliant C-compiler, #include "file.h" zal waarschijnlijk gaan zoeken naar ./file.h eerst waar . is de map waar is het bestand met de #include verklaring, terwijl #include <file.h>, zal waarschijnlijk gaan zoeken naar /usr/include/file.h eerst waar /usr/include is uw systeem gedefinieerd gebruikelijke plaatsen voor headers (het lijkt niet gedefinieerd door POSIX).


92
2017-07-20 09:29



Het doet:

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

met . ofwel de map van het bestand waar de #include is opgenomen in, en / of de huidige werkdirectory van de compiler, en / of de default_include_paths

en

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

Als ./ is in <default_include_paths>, dan maakt het geen verschil.

Als mypath/myfile bevindt zich in een andere map opnemen, het gedrag is niet gedefinieerd.


36
2018-02-08 11:45



GCC-documentatie zegt het volgende over het verschil tussen de twee:

Zowel gebruikers- als systeemkopregelbestanden worden opgenomen met behulp van de voorbewerkingsrichtlijn ‘#include’. Het heeft twee varianten:

#include <file>

Deze variant wordt gebruikt voor systeemkopregelbestanden. Het zoekt naar een bestand met de naam bestand in een standaardlijst met systeemmappen. U kunt mappen toevoegen aan deze lijst met de -I optie (zie Aanroeping).

#include "file"

Deze variant wordt gebruikt voor header-bestanden van uw eigen programma. Het zoekt eerst naar een bestand met de naam bestand in de map met het huidige bestand, vervolgens naar de citaatmappen en vervolgens naar dezelfde mappen <file>. U kunt mappen toevoegen aan de lijst met citaatmappen met de -iquote keuze.     Het argument van ‘#include’, begrensd door aanhalingstekens of punthaken, gedraagt ​​zich als een reeksconstante doordat opmerkingen niet worden herkend en de macronamen niet worden uitgebreid. Dus, #include <x/*y> specificeert opname van een genoemd systeem header bestand x/*y.

Als backslashes echter voorkomen in het bestand, worden ze beschouwd als gewone teksttekens, geen escape-tekens. Geen van de karakterontsnappingsreeksen die geschikt zijn voor stringconstanten in C worden verwerkt. Dus,#include "x\n\\y"geeft een bestandsnaam op met drie backslashes. (Sommige systemen interpreteren '\' als een padnaam-scheidingsteken, die ook allemaal worden geïnterpreteerd ‘/’ dezelfde manier. Het is het meest draagbaar om alleen te gebruiken ‘/’.)

Het is een fout als er iets (behalve opmerkingen) op de regel achter de bestandsnaam staat.


30
2018-01-14 04:52



De <file> include vertelt de preprocessor om in te zoeken -I mappen en in vooraf gedefinieerde mappen eerste, dan in de directory van het .c-bestand. De "file" include vertelt de preprocessor om de map van het bronbestand te doorzoeken eersteen keer dan terug naar -I en voorgedefinieerd. Alle bestemmingen worden toch doorzocht, alleen de volgorde van zoeken is anders.

De 2011-standaard bespreekt meestal de include-bestanden in "16.2 Bronbestand-integratie".

2 Een voorbewerkingsrichtlijn van het formulier

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

doorzoekt een reeks met implementatie gedefinieerde plaatsen voor een header die uniek is geïdentificeerd door de   opgegeven reeks tussen de <en> scheidingstekens en veroorzaakt de   vervanging van die richtlijn door de volledige inhoud van de header.   Hoe de plaatsen worden gespecificeerd of de geïdentificeerde header is   -Implementatie gedefinieerd.

3 Een voorbewerkingsrichtlijn van het formulier

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

veroorzaakt de vervanging van die richtlijn door de volledige inhoud van het bronbestand geïdentificeerd door de   gespecificeerde volgorde tussen de "scheidingstekens." Het genoemde bronbestand is   gezocht op een door de implementatie gedefinieerde manier. Als deze zoekopdracht is   niet ondersteund of als het zoeken mislukt, wordt de richtlijn opnieuw verwerkt   als het leest

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

met de identieke ingesloten reeks (inclusief> tekens, indien aanwezig) van de oorspronkelijke richtlijn.

Let daar op "xxx" vorm degradeert tot <xxx> formulier als het bestand niet is gevonden. De rest is door de implementatie gedefinieerd.


23
2017-09-03 12:17



Volgens de standaard - ja, ze zijn verschillend:

  • Een voorbewerkingsrichtlijn van het formulier

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

    doorzoekt een reeks met implementatie gedefinieerde plaatsen voor een header die uniek is geïdentificeerd door de opgegeven reeks tussen de < en > scheidingstekens en zorgt ervoor dat die richtlijn door de volledige inhoud van de kop wordt vervangen. Hoe de plaatsen worden gespecificeerd of de header die wordt geïdentificeerd, is door de implementatie gedefinieerd.

  • Een voorbewerkingsrichtlijn van het formulier

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

    veroorzaakt de vervanging van die richtlijn door de volledige inhoud van het bronbestand geïdentificeerd door de opgegeven reeks tussen de " scheidingstekens. Het genoemde bronbestand wordt op een door de implementatie gedefinieerde manier gezocht. Als deze zoekopdracht niet wordt ondersteund of als het zoeken mislukt, wordt de richtlijn opnieuw verwerkt alsof deze zou kunnen worden gelezen

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

    met de identieke ingesloten reeks (inclusief > tekens, indien aanwezig) van het origineel   richtlijn.

  • Een voorbewerkingsrichtlijn van het formulier

    #include pp-tokens new-line
    

    (dat komt niet overeen met een van de twee voorgaande formulieren) is toegestaan. De preprocessing tokens after include in de richtlijn worden net als in normale tekst verwerkt. (Elke ID die momenteel is gedefinieerd als een macronaam wordt vervangen door de vervangende lijst van voorbewerkingstokens.) De richtlijn die na alle vervangingen ontstaat, moet overeenkomen met een van de twee voorgaande formulieren. De methode waarmee een reeks voorbewerkingstokens tussen a < en een > preprocessing token pair of een paar " tekens worden gecombineerd in een enkele headernaam preprocessing token is door de implementatie gedefinieerd.

Definities:

  • h-char: elk lid van de bronsetset, behalve het teken van de nieuwe regel en >

  • q-char: elk lid van de bronsetset met uitzondering van het karakter van de nieuwe regel en "

Merk op dat de standaard geen enkele relatie aangeeft tussen de door implementatie gedefinieerde manieren. Het eerste formulier zoekt op de ene manier en op de andere manier, en de ander op een (mogelijk andere), op implementatie gedefinieerde manier. De standaard geeft ook aan dat bepaalde include-bestanden aanwezig moeten zijn (bijvoorbeeld <stdio.h>).

Formeel zou je de handleiding van je compiler moeten lezen, echter normaal (volgens de traditie) de #include "..." form zoekt in de map van het bestand waarin de #include werd eerst gevonden, en vervolgens de mappen die de #include <...> form searches (het include-pad, bijv. systeemheaders).


16
2017-08-18 06:21



Bedankt voor de geweldige antwoorden, in het bijzonder Adam Stelmaszczyk en piCookie, en aib.

Zoals veel programmeurs heb ik de informele conventie gebruikt van het gebruik van de "myApp.hpp" formulier voor applicatiespecifieke bestanden, en de <libHeader.hpp> formulier voor bibliotheek- en compilersysteembestanden, d.w.z. bestanden die zijn opgegeven in /I en de INCLUDE omgevingsvariabele, jarenlang denken dat dat de standaard was.

In de C-standaard staat echter dat de zoekvolgorde implementatiespecifiek is, wat de draagbaarheid ingewikkeld kan maken. Om het nog erger te maken, gebruiken we jam, die automatisch uitzoekt waar de include-bestanden zijn. U kunt relatieve of absolute paden gebruiken voor uw include-bestanden. d.w.z.

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

Oudere versies van MSVS vereisten dubbele backslashes (\\), maar dat is nu niet nodig. Ik weet niet wanneer het veranderde. Gebruik gewoon slashes voor compatibiliteit met 'nix' (Windows accepteert dat).

Als je bent werkelijk erover bezorgd, gebruik "./myHeader.h" voor een include-bestand in dezelfde map als de broncode (mijn huidige, zeer grote project bevat enkele duplicaten inclusief bestandsnamen - echt een probleem met configuratiebeheer).

Hier is de MSDN-uitleg hier voor uw gemak gekopieerd).

Geciteerd formulier

De preprocessor zoekt naar bestanden in deze volgorde:

  1. In dezelfde map als het bestand met de instructie #include.
  2. In de mappen van de momenteel geopende include-bestanden, in de omgekeerde volgorde waarin
        ze waren geopend. Het zoeken begint in de directory van de ouder inclusief bestand en
        gaat verder omhoog door de mappen van elke grootouder inclusief bestanden.
  3. Langs het pad dat door elk pad is opgegeven /I compiler optie.
  4. Langs de paden die zijn opgegeven door de INCLUDE omgevingsvariabele.

Hoek-beugel vorm

De preprocessor zoekt naar bestanden in deze volgorde:

  1. Langs het pad dat door elk pad is opgegeven /I compiler optie.
  2. Wanneer compileren plaatsvindt op de opdrachtregel, langs de paden die zijn opgegeven door de INCLUDE omgevingsvariabele.

12
2017-10-14 23:51



In ieder geval voor GCC-versie <= 3.0, genereert het hoek-haak formulier geen afhankelijkheid tussen het opgenomen bestand en het bijbehorende bestand.

Dus als u afhankelijkheidsregels wilt genereren (bijvoorbeeld met de GCC-M-optie), moet u het geciteerde formulier gebruiken voor de bestanden die moeten worden opgenomen in de afhankelijkheidsstructuur.

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


11
2017-10-25 12:35