В чем разница между #include <filename> и #include "filename"?

В чем разница между использованием угловых скобок и кавычек в операторе include в языках программирования C и C++, как показано ниже?

  1. #include <filename>
  2. #include "filename"
Где GCC ищет файлы заголовков
theoretisch 10.08.2016 14:52

Чтобы узнать о поведении Visual Studio, проверьте: docs.microsoft.com/en-us/cpp/preprocessor/…

smwikipedia 17.03.2020 08:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2 550
3
657 045
30

Ответы 30

На практике разница заключается в том, где препроцессор ищет включенный файл.

Для #include <filename> препроцессор выполняет поиск в зависимости от реализации, обычно в каталогах поиска, предварительно назначенных компилятором / IDE. Этот метод обычно используется для включения файлов заголовков стандартной библиотеки.

Для #include "filename" препроцессор сначала выполняет поиск в том же каталоге, что и файл, содержащий директиву, а затем следует пути поиска, используемому для формы #include <filename>. Этот метод обычно используется для включения файлов заголовков, определенных программистом.

Более полное описание доступно в GCC документация по путям поиска.

Утверждение: «препроцессор ищет в том же каталоге ...» может быть верным на практике, но стандарт утверждает, что именованный исходный файл «ищется способом, определяемым реализацией». См. Ответ от piCookie.

Richard Corden 17.09.2008 17:41

Хотя ваш ответ может показаться «правдой», поскольку именно столько реализаций работают по соглашению, вам следует внимательно изучить ответы aib и piCookie. Они оба указывают (поддержанные формулировкой стандарта C), что реальное различие заключается в включении «заголовка» по сравнению с включением «исходного файла» (и нет, это не означает «.h» против «. c "). «Исходный файл» в этом контексте может быть (и обычно является и почти всегда должен быть) файлом «.h». Заголовок не обязательно должен быть файлом (компилятор может, например, включать статически закодированный заголовок, а не в файл).

Dan Moulding 17.08.2009 20:30

«... препроцессор ищет в том же каталоге, что и компилируемый файл, файл, который нужно включить». Это утверждение не совсем верно. Меня заинтересовал этот вопрос, потому что мне было любопытно, каков фактический ответ, но я знаю, что это неправда, потому что, по крайней мере, с gcc, когда вы указываете дополнительный путь включения с -I, который будет искать файлы, указанные с #include "filename. час"

Gabriel Southern 13.03.2012 01:49

Тем, кому ответ не нравится, приведите, пожалуйста, один практический пример, где он неверен.

0kcats 08.11.2017 23:46

Конечно, недавно я смешал эти синтаксисы при включении заголовков из «той же» библиотеки и в итоге получил ошибки переопределения. Если я правильно понимаю, #include <...> использовал пакет, установленный в системе, а #include "..." использовал версию из ближайшего репозитория. Я мог бы сделать это наоборот. В любом случае, защита включения в упакованном заголовке имеет префикс подчеркивания. (Это может быть соглашение для пакетов или, может быть, способ намеренно предотвратить их смешивание, хотя квалификаторы версии будут для меня более понятными.)

John P 23.02.2018 03:21

Почему у некоторых пользователей Windows файл #includepch.h заключен в кавычки? Это не что-то вроде "определенного программистами" файла.

Kamran Poladov 04.10.2018 21:53

По сути, он позволяет «исправлять» включенное содержимое во время компиляции, чтобы «переопределить» обычный путь включения. Это предотвращает искажение чужого исходного (скажем, из библиотеки github) источника. Это очень распространено для библиотек и даже ядер Arduino.

mckenzm 25.01.2019 12:21

«Один практический пример, когда это неправильно» не имеет значения. Стандарты существуют не зря. Рекомендация (в стандарте) - использовать <> для заголовков, включенных в реализацию, "" для всего остального. Но ясно, что это только руководство, пути поиска для обоих случаев определены реализацией, за исключением того факта, что "" вернется к <>, если он не может быть найден.

paxdiablo 10.01.2020 02:58

Обычно нормально нормально o:

Tilak Maddy 10.04.2020 10:56

<file> include указывает препроцессору искать в каталогах -I и в предварительно определенных каталогах первый, а затем в каталоге файла .c. "file" include сообщает препроцессору, что нужно выполнить поиск в каталоге первый исходного файла, а затем вернуться к -I и предопределенному. Все равно ищутся все направления, отличается только порядок поиска.

Стандарт 2011 года в основном обсуждает включаемые файлы в «16.2 Включение исходного файла».

2 A preprocessing directive of the form

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

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

3 A preprocessing directive of the form

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

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

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

with the identical contained sequence (including > characters, if any) from the original directive.

Обратите внимание, что форма "xxx" ухудшается до формы <xxx>, если файл не найден. Остальное определяется реализацией.

Не могли бы вы указать, где в стандарте C указывается этот бизнес -I?

juanchopanza 28.12.2014 07:31

Не вижу ссылки на -I.

juanchopanza 28.12.2014 21:49

Это часть, «определяемая реализацией».

user3458 29.12.2014 17:40

Последовательность символов между однозначно относится к заголовку, который не обязательно является файлом. Реализации могут свободно использовать последовательность символов по своему усмотрению. (В большинстве случаев, однако, просто рассматривайте это как имя файла и выполняйте поиск в включить путь, как указано в других сообщениях.)

Если используется форма #include "file", реализация сначала ищет файл с заданным именем, если он поддерживается. Если не (поддерживается) или поиск завершается неудачно, реализация ведет себя так, как если бы использовалась другая (#include <file>) форма.

Кроме того, существует третья форма, которая используется, когда директива #include не соответствует ни одной из форм выше. В этой форме некоторая базовая предварительная обработка (такая как расширение макроса) выполняется для «операндов» директивы #include, и ожидается, что результат будет соответствовать одной из двух других форм.

+1, это, наверное, самый лаконичный и правильный ответ здесь. Согласно стандарту (который цитирует piCookie в своем ответе), единственное отличие настоящий - это «заголовок» и «исходный файл». В любом случае механизм поиска определяется реализацией. Использование двойных кавычек означает, что вы намереваетесь включить «исходный файл», а угловые скобки означают, что вы намереваетесь включить «заголовок», который, как вы говорите, может быть вовсе не файлом.

Dan Moulding 17.08.2009 20:12

Я знаю, что спрашиваю об этом спустя много времени после того, как вы опубликовали ответ, но @aib, что вы имеете в виду под «уникальной ссылкой на заголовок, который не обязательно является файлом»? Даже заголовочные файлы - это файлы!

Nav 27.01.2011 09:38

См. Комментарий Дэна Моулдинга к ответу quest49; стандартные заголовки не обязательно должны быть в виде файлов, они могут быть встроенными.

aib 27.01.2011 12:28

Я читал это «стандартные заголовки не обязательно должны быть в виде файлов» уже десять лет. Хотите привести реальный пример?

Maxim Egorushkin 08.02.2011 14:54

@ Максим Егорушкин: Я тоже не могу вспомнить ни одного существующего реального примера; однако полный компилятор C11 не может существовать для MS-DOS, если заголовки не обязательно должны быть файлами. Это связано с тем, что некоторые имена заголовков C11 несовместимы с ограничением имени файла MS-DOS «8.3».

Dan Moulding 12.10.2012 16:35

Заголовки не обязательно являются файлами. Если вы напишете #include , заголовок может быть непосредственно встроен в компилятор.

gnasher729 24.02.2014 00:55

@DanMoulding: компиляторы на основе MS-DOS, которые я видел, почти всегда интерпретируют #include "thisIsAVeryLongName.and.I.Love.Dots.h" as a request to read a file THISISAV.AND`; можно было бы выдать предупреждение, что имя в директиве не соответствует файлу; остальные, которые я видел, просто проигнорируют это. Не будет ли какой-либо из заголовков, необходимых для C11, работать в такой модели, например потому что два разных имени имеют общий префикс из 8 букв?

supercat 15.08.2015 20:57

@MaximEgorushkin: Компилятор VAX / VMS C хранил все заголовки библиотеки времени выполнения C в одном текстовом файле библиотеки (аналогично архиву unix) и использовал строку между < и > в качестве ключа для индексации в библиотеке.

Adrian McCarthy 16.02.2017 02:14
заголовок, который не обязательно является файлом -- reminds me of URLs (mostly files in the beginning and these days everything you can think of)
Wolf 11.12.2017 19:32

Единственный способ узнать это - прочитать документацию по вашей реализации.

В пунктах 2–4 раздела 6.10.2 стандарт C говорится:

  • A preprocessing directive of the form

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

    searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

  • A preprocessing directive of the form

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

    causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

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

    with the identical contained sequence (including > characters, if any) from the original directive.

  • A preprocessing directive of the form

    #include pp-tokens new-line
    

    (that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

Definitions:

  • h-char: any member of the source character set except the new-line character and >

  • q-char: any member of the source character set except the new-line character and "

Актуально: реализация в g ++ и в визуальный C++

Alexander Malakhov 10.10.2012 07:48

@piCookie оба и "имя файла" поиск мест, определенных реализацией. Так в чем разница?

onmyway133 04.02.2013 07:45

@entropy: На таком форуме невозможно ответить на ваш вопрос. Ответ, который был бы правильным для одного конкретного компилятора, мог быть совершенно неправильным для другого. Каждая конкретная реализация / компилятор должна быть обязана разъяснять разницу, и это единственный надежный способ узнать. В нескольких других ответах приведены примеры, и, возможно, ваша реализация упоминается в одном из них.

piCookie 05.02.2013 20:38

@piCookie, но можно сказать, что угловые скобки проверяют INCLUDE_PATH, а "" - нет. Таким образом, угловые скобки представляют путь поиска, но вовсе не cwd. на самом деле нет никакой разницы, если вы уменьшите ее до точки, которая ищет только по стандартному пути включения.

Stefan 23.08.2013 23:12

@Stefan, я просто цитирую стандарт, в котором ничего не говорится о INCLUDE_PATH. Ваша реализация может это сделать, а моя - нет. Исходный вопрос был в общем C, а не конкретно gcc (который, я не думаю, использует INCLUDE_PATH) или Microsoft C (который, я думаю, использует) или любой другой, поэтому на него нельзя ответить в общем виде, но вместо этого необходимо ссылаться на документацию по каждой реализации.

piCookie 25.08.2013 04:22

@piCookie нет. INCLUDE_PATH больше предназначался как переменная, содержащая стандартные пути для компилятора, а не конкретная деталь реализации поставщика.

Stefan 25.08.2013 16:28

Как и во всех этих ситуациях, конкретные примеры (особенно общих сценариев) очень полезны и одинаково ценятся. Излишне тупые общие ответы не имеют такого практического применения.

vargonian 29.04.2014 21:51

Я точно не знаю, как это в C, но если я прочитал стандартную цитату выше, последовательность между < и > не обязательно должна быть именем файла. Подойдет все, что однозначно определяет заголовок. В C++ это означает, что не обязательно отображается в файл с именем «алгоритм» или «алгоритм.h». Как на самом деле назван этот файл, или если заголовок даже является файлом в файловой системе, определяется реализацией. Но q-char-последовательность во второй версии действительно содержит настоящее имя файла.

Rudy Velthuis 08.06.2014 21:55

@ onmyway133 стандарт позволяет использовать механизмы поиска дваальтернатива. Если механизм поиска анальтернатива (для включают "") не реализован, включают "" функционирует как включают. Однако у этой цитаты из стандартов обязательно должно быть резюме - никому не нужно тратить время на выяснение того, что она подразумевает.

cloudcell 17.01.2015 16:12

«Вот как стандарт C может быть многословным и не отвечать на ваш вопрос»

anatolyg 29.03.2015 22:32

«Единственный способ узнать это - прочитать документацию по вашей реализации». Или спросив кого-нибудь на Stack Overflow. Я ценю, что вы выбрали «обучающий момент», но боюсь, что такое отношение быстро устаревает.

Jacksonkr 04.05.2016 16:45

"оба и "имя файла" поиск мест, определяемых реализацией ". Чем этот ответ практически полезен?

Maxim Egorushkin 17.09.2016 16:32

@MaximEgorushkin см. В комментарии Александра Малахова ссылки, описывающие реализацию для gcc и Visual C++. Аналогичная документация должна быть и для любого другого коммерческого компилятора. ИМО, комментарий Александра должен быть частью ответа.

akhan 02.10.2016 00:25

Люди приходят сюда, чтобы им объяснили вещи в понятной для них манере. Простое указание на загадочную документацию бесполезно. Именно из-за этой плохой документации так многие из нас задаются этим вопросом.

Dave Voyles 07.11.2016 22:00

@ DaveVoyles-MSFT, это единственный правильный ответ, потому что вопрос не указывал, какая реализация, а только «языки программирования C и C++». Как некоторые реализации обрабатывают #include, уже указывалось в комментариях, и это их место, потому что они на самом деле не ответят на вопрос.

osvein 15.06.2017 15:44

Если ответ должен быть полезен, он должен указывать на предполагаемую цель и общее использование этих директив, а не только цитировать стандарт, в котором рассказывается, как вещи определены, но не объясняется, почему. Ответ должен включать тот факт, что используется для включения заголовков стандартной библиотеки, а "" используется для включения локальных включений проекта.

Suma 08.07.2018 10:18

Целью цитирования стандарта является показать, что стандарт не дает ответа, так как разница, если таковая имеется, между этими двумя формами полностью зависит от реализации, поэтому цитирование стандарта предполагалось, предлагая вам прочитать свой соответствующая документация по реализации, потому что OP не указала, какова была их реализация. Проще говоря: стандартного ответа не существует, поэтому вы ДОЛЖНЫ проконсультироваться с соответствующей документацией по вашей реализации, чтобы выяснить это для вашего конкретного случая.

SteamyThePunk 04.09.2018 20:36

Оно делает:

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

где . является либо каталогом файла, в котором содержится #include, и / или текущим рабочим каталогом компилятора, и / или default_include_paths

и

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

Если ./ находится в <default_include_paths>, это не имеет значения.

Если mypath/myfile находится в другом подключаемом каталоге, поведение не определено.

Нет, #include "mypath/myfile" не эквивалентен #include "./mypath/myfile". Как говорится в ответе piCookie, двойные кавычки говорят компилятору выполнять поиск в соответствии с определенным реализацией способом, который включает поиск в местах, указанных для #include <...>. (На самом деле, это, вероятно, эквивалентно, но только потому, что, например, /usr/include/mypath/myfile может называться /usr/include/./mypath/myfile - по крайней мере, в Unix-подобных системах.)

Keith Thompson 08.09.2011 03:03

@Keith Thompson: Верно, я думал о своем Linux-компьютере. Видимо могло быть иначе. Хотя на практике Windows как операционная система, отличная от Posix, также интерпретирует / как разделитель путей, и ./ также существует.

Stefan Steiger 03.04.2014 13:23

опция -L dirpath затем добавляет dirpath к defaultincludepaths, вместо того, чтобы придавать другое значение . (как указано выше). Это имеет ожидаемые последствия, что и #include "...", и #include <...> будут искать в dirpath.

Protongun 06.04.2014 22:07

Я думаю, что этот ответ неверен, поскольку он подразумевает, что заголовки, заключенные в двойные кавычки, всегда ищутся в текущем рабочем каталоге. Механизм поиска более подробный; этот ответ неполный. Я добавляю этот комментарий не для того, чтобы жаловаться или хныкать, а потому, что система просит меня добавить комментарий, чтобы объяснить, почему я отклонил этот ответ.

Carlo Wood 28.09.2016 02:06

Для #include "" компилятор обычно выполняет поиск в папке файла, который содержит это include, а затем в других папках. Для #include <> компилятор не выполняет поиск в папке текущего файла.

Не уверен, почему люди не согласны.

Maxim Egorushkin 27.03.2012 10:30

Я подозреваю, что это потому, что большинство людей компилируют только файлы в своем CWD. Если вы находитесь в каталоге foo, и вы компилируете foo / unittest / bar.c, и он включает bar.h, тогда "bar.h" работает и не.

user3458 30.03.2012 18:07

@Maxim люди не согласны, потому что поведение, которое вы описываете, не является стандартным C.

osvein 25.07.2015 15:16

@Spookbuster Верно, в стандарте говорится, что <filename> и "filename" ищут места, определенные реализацией.

Maxim Egorushkin 17.09.2016 16:33

#Include с угловыми скобками будет искать файл, который нужно включить, в «зависящем от реализации списке мест» (что является очень сложным способом сказать «системные заголовки»).

#Include с кавычками будет просто искать файл (и «в зависимости от реализации», bleh). Это означает, что на обычном английском языке он попытается применить путь / имя файла, которые вы ему укажете, и не будет добавлять системный путь в начале или вмешиваться в него в противном случае.

Кроме того, если #include "" не удается, он перечитывается как #include по стандарту.

документация gcc имеет (специфичное для компилятора) описание, которое, хотя и относится к gcc, а не к стандарту, намного проще для понимания, чем разговоры адвоката о стандартах ISO.

Однако использование угловых скобок или кавычек не влияет на способ включения файлов, это точно так же: препроцессор фактически создает большой исходный файл, копируя и вставляя код из включаемых файлов в исходный исходный файл, прежде чем дать это в компилятор (препроцессор выполняет другие действия, например #define sustitution, #if оценка и т. д., но обработка #include настолько проста)

Loghorn 08.02.2011 15:59

А как насчет конфликтов? например, скажем, у меня есть zlib.h в моих «пользовательских» путях поиска, и другая версия существует в системном пути поиска, тогда #include <zlib.h> включает системную версию, а #include "zlib.h" включает мою собственную?

the_mandrill 08.02.2011 16:10

Ага, ответил на свой вопрос: stackoverflow.com/questions/21593/…

the_mandrill 08.02.2011 16:10

Благодарим вас за подтверждение того, что оба стандартных соглашения о реализации и имеют здесь значение, а не просто заявляют, что это неизвестно, потому что это не определено стандартом.

Kyle Strand 27.07.2016 20:45

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

Пример:

Имя файла здесь 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

В реализации класса (например, Seller.cpp и в других файлах, которые будут использовать файл Seller.h) теперь должен быть включен заголовок, определенный пользователем, как показано ниже:

#include "Seller.h"

По крайней мере, для версии GCC

Поэтому, если вы хотите сгенерировать правила зависимостей (например, используя опцию GCC -M), вы должны использовать цитируемую форму для файлов, которые должны быть включены в дерево зависимостей.

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

Да, есть несколько разных способов создания зависимостей. Это один из них, но не единственный.

Pryftan 22.11.2019 02:01

Некоторые хорошие ответы здесь содержат ссылки на стандарт C, но забыли стандарт POSIX, особенно конкретное поведение команды c99 (например, компилятор C).

Согласно Базовые спецификации Open Group, выпуск 7,

-Idirectory

Change the algorithm for searching for headers whose names are not absolute pathnames to look in the directory named by the directory pathname before looking in the usual places. Thus, headers whose names are enclosed in double-quotes ( "" ) shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets ( "<>" ), the header shall be searched for only in directories named in -I options and then in the usual places. Directories named in -I options shall be searched in the order specified. Implementations shall support at least ten instances of this option in a single c99 command invocation.

Таким образом, в POSIX-совместимой среде с POSIX-совместимым компилятором C #include "file.h", вероятно, сначала будет искать ./file.h, где . - это каталог, в котором находится файл с оператором #include, а #include <file.h>, скорее всего, сначала будет искать /usr/include/file.h. , где /usr/include - это обычные места, определенный вашей системой для заголовков (похоже, не определен в POSIX).

Каков точный источник текста? Это из нормативной части IEEE Std 1003.1, 2013?

osgx 12.03.2015 05:34

@osgx: эта формулировка (или что-то очень похожее) находится в спецификации POSIX для c99 - это имя POSIX для компилятора C. (Стандарт POSIX 2008 вряд ли может относиться к C11; обновление 2013 года до POSIX 2008 не изменило стандарт C, на который он ссылался.)

Jonathan Leffler 10.11.2016 06:40

Это была и моя первая мысль. Справочная страница для gcc включает это, как и другие. То же самое и с библиотеками - -L.

Pryftan 22.11.2019 01:55
  • #include <> предназначен для предопределенных файлов заголовков

Если файл заголовка предопределен, вы просто должны написать имя файла заголовка в угловых скобках, и это будет выглядеть так (при условии, что у нас есть предопределенное имя файла заголовка iostream):

#include <iostream>
  • #include " " предназначен для файлов заголовков, определяемых программистом.

Если бы вы (программист) написали свой собственный файл заголовка, вы бы написали имя файла заголовка в кавычках. Итак, предположим, вы написали заголовочный файл с именем myfile.h, тогда это пример того, как вы могли бы использовать директиву include для включения этого файла:

#include "myfile.h"

Это вообще не имеет ничего общего с предопределенными файлами заголовков. Это связано с местами, которые нужно искать.

C Johnson 23.04.2019 18:29

Простое общее правило - использовать угловые скобки для включения файлов заголовков, поставляемых с компилятором. Используйте двойные кавычки для включения любых других файлов заголовков. Большинство компиляторов делают это именно так.

1.9 - Заголовочные файлы объясняет более подробно директивы препроцессора. Если вы начинающий программист, эта страница должна помочь вам во всем этом разобраться. Я узнал об этом отсюда и слежу за этим на работе.

Многие ответы здесь сосредоточены на путях, которые компилятор будет искать, чтобы найти файл. Хотя это то, что делают большинство компиляторов, соответствующий компилятор может быть предварительно запрограммирован с использованием эффектов стандартных заголовков и обрабатывать, скажем, #include <list> как переключатель, и он вовсе не обязательно должен существовать как файл.

Это не чисто гипотетическое. По крайней мере, один компилятор работает таким образом. Рекомендуется использовать #include <xxx> только со стандартными заголовками.

#include <filename> используется при обращении к системному файлу. Это файл заголовка, который можно найти в системных местоположениях по умолчанию, таких как /usr/include или /usr/local/include. Для ваших собственных файлов, которые необходимо включить в другую программу, вы должны использовать синтаксис #include "filename".

Спасибо за отличные ответы, особенно. Адам Стельмашчик и piCookie, и аиб.

Как и многие программисты, я использовал неформальное соглашение об использовании формы "myApp.hpp" для конкретных файлов приложения и формы <libHeader.hpp> для системных файлов библиотеки и компилятора, то есть файлов, указанных в /I и переменной среды INCLUDE, в течение многих лет считая, что это стандарт.

Однако в стандарте C указано, что порядок поиска зависит от реализации, что может затруднить переносимость. Что еще хуже, мы используем jam, который автоматически определяет, где находятся включаемые файлы. Вы можете использовать относительные или абсолютные пути для ваших включаемых файлов. т.е.

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

В более старых версиях MSVS требовалась двойная обратная косая черта (\\), но теперь это не требуется. Не знаю, когда это изменилось. Просто используйте косую черту для совместимости с 'nix (Windows примет это).

Если вас это беспокоит В самом деле, используйте "./myHeader.h" для включаемого файла в том же каталоге, что и исходный код (в моем текущем, очень большом проекте есть несколько повторяющихся имен включаемых файлов, разбросанных по сторонам - на самом деле проблема управления конфигурацией).

Вот Объяснение MSDN, скопированный сюда для вашего удобства).

Quoted form

The preprocessor searches for include files in this order:

  1. In the same directory as the file that contains the #include statement.
  2. In the directories of the currently opened include files, in the reverse order in which
    they were opened. The search begins in the directory of the parent include file and
    continues upward through the directories of any grandparent include files.
  3. Along the path that's specified by each /I compiler option.
  4. Along the paths that are specified by the INCLUDE environment variable.

Angle-bracket form

The preprocessor searches for include files in this order:

  1. Along the path that's specified by each /I compiler option.
  2. When compiling occurs on the command line, along the paths that are specified by the INCLUDE environment variable.

#include <filename>

используется, когда вы хотите использовать файл заголовка системы C / C++ или библиотек компилятора. Эти библиотеки могут быть stdio.h, string.h, math.h и т. д.

#include "path-to-file/filename"

используется, когда вы хотите использовать свой собственный файл заголовка, который находится в папке вашего проекта или где-то еще.

Для получения дополнительной информации о препроцессорах и заголовке. Прочтите C - Препроцессоры.

По стандарту - да, разные:

  • A preprocessing directive of the form

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

    searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

  • A preprocessing directive of the form

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

    causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read

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

    with the identical contained sequence (including > characters, if any) from the original directive.

  • A preprocessing directive of the form

    #include pp-tokens new-line
    

    (that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

Definitions:

  • h-char: any member of the source character set except the new-line character and >

  • q-char: any member of the source character set except the new-line character and "

Обратите внимание, что в стандарте не говорится о какой-либо связи между способами, определяемыми реализацией. Первая форма выполняет поиск одним способом, определяемым реализацией, а другая (возможно, другим) способом, определяемым реализацией. Стандарт также указывает, что должны присутствовать определенные включаемые файлы (например, <stdio.h>).

Формально вам нужно прочитать руководство для вашего компилятора, однако обычно (по традиции) форма #include "..." выполняет поиск в каталоге файла, в котором сначала был найден #include, а затем в каталогах, которые ищет форма #include <...> (путь включения, например, системные заголовки).

В основном это тот же текст, что и ранее полученный ответ piCookie от семь лет.

Kyle Strand 27.07.2016 20:43

@KyleStrand Это потому, что тот же текст является цитатой из соответствующего раздела в стандарте - этот текст должен должен быть идентичным. Фактический ответ - это не тот же текст и несколько отличается - хотя я также признаю, что он будет написан в документации для реализации, я также отмечаю, что существует также традиционный способ их интерпретации (что большинство или все компиляторы, которые я использовал, уважают) .

skyking 28.07.2016 10:25

ИМО, это лучший ответ здесь, потому что он охватывает как то, что говорит стандарт, так и то, что на самом деле делают большинство компиляторов.

plugwash 11.09.2016 16:59

В C++ включить файл можно двумя способами:

Первый - #include, который указывает препроцессору искать файл в заранее определенном месте по умолчанию. Это расположение часто является переменной среды INCLUDE, которая указывает путь для включения файлов.

И второй тип - это #include «filename», который сообщает препроцессору, что сначала нужно искать файл в текущем каталоге, а затем искать его в заранее определенных местах, которые пользователь установил.

В документации GCC говорится следующее о разнице между ними:

Both user and system header files are included using the preprocessing directive ‘#include’. It has two variants:

#include <file>

This variant is used for system header files. It searches for a file named file in a standard list of system directories. You can prepend directories to this list with the -I option (see Invocation).

#include "file"

This variant is used for header files of your own program. It searches for a file named file first in the directory containing the current file, then in the quote directories and then the same directories used for <file>. You can prepend directories to the list of quote directories with the -iquote option. The argument of ‘#include’, whether delimited with quote marks or angle brackets, behaves like a string constant in that comments are not recognized, and macro names are not expanded. Thus, #include <x/*y> specifies inclusion of a system header file named x/*y.

However, if backslashes occur within file, they are considered ordinary text characters, not escape characters. None of the character escape sequences appropriate to string constants in C are processed. Thus,#include "x\n\y"specifies a filename containing three backslashes. (Some systems interpret ‘\’ as a pathname separator. All of these also interpret ‘/’ the same way. It is most portable to use only ‘/’.)

It is an error if there is anything (other than comments) on the line after the file name.

Что такое «каталог котировок»?

Jack M 30.07.2020 16:31

@JackM • имеется 3 места: Текущий каталог файла #include, каталоги котировок (пути для проверки стиля #include "foo.h" включают) и системные каталоги (пути для проверки стиля #include <bar.h>).

Eljay 02.08.2020 16:29

Что означает «система» во фразе «системный заголовочный файл»? Я обнаружил, что компьютерные ученые часто используют слово «система», и я часто не могу сказать, означает ли оно «операционная система», «компьютерная система» или что-то еще.

littleO 15.11.2020 03:56

#include <abc.h>

используется для включения файлов стандартной библиотеки. Таким образом, компилятор проверит места, где находятся заголовки стандартных библиотек.

#include "xyz.h"

скажет компилятору включить определяемые пользователем файлы заголовков. Таким образом, компилятор проверит эти файлы заголовков в текущей папке или в папках, определенных -I.

#include <file.h> сообщает компилятору, что нужно искать заголовок в его «включаемом» каталоге, например для MinGW компилятор будет искать file.h в C: \ MinGW \ include \ или там, где установлен ваш компилятор.

#include "file" сообщает компилятору, что нужно искать file в текущем каталоге (т.е. в каталоге, в котором находится исходный файл).

Вы можете использовать флаг -I для GCC, чтобы сообщить ему, что, когда он встречает включение с угловыми скобками, он также должен искать заголовки в каталоге после -I. GCC будет обрабатывать каталог после флага, как если бы это был каталог includes.

Например, если у вас есть файл с именем myheader.h в вашем собственном каталоге, вы можете сказать #include <myheader.h>, если вы вызвали GCC с флагом -I . (что означает, что он должен искать включения в текущем каталоге).

Без флага -I вам придется использовать #include "myheader.h" для включения файла или переместить myheader.h в каталог include вашего компилятора.

the " < filename > " searches in standard C library locations

whereas "filename" searches in the current directory as well.

В идеале вы должны использовать <...>для стандартных библиотек C и "..." для библиотек, которые вы пишете и присутствуют в текущем каталоге.

Какая новая информация добавляет этот ответ к другим?

Daniel Langr 28.03.2018 14:40

Когда вы используете #include , препроцессор ищет файл в каталоге файлов заголовков C \ C++ (stdio.h \ cstdio, string, vector и т. д.). Но, когда вы используете #include «filename»: сначала препроцессор ищет файл в текущем каталоге, а если его здесь нет - он ищет его в каталоге файлов заголовков C \ C++.

После того, как идеальный ответ был доступен в течение многих лет, зачем присылать его, ведь это явно неверно? Несмотря на то, что директива #include широко распространена, она вообще не связана строго с файлами.

IInspectable 02.10.2018 22:31

@IInspectable, пожалуйста, объясните, почему это вообще не связано с файлами.

Behrooz Karjoo 26.02.2019 23:06

Форма 1 - #include

Сначала проверяет наличие заголовочного файла в текущем каталоге, откуда вызывается директива. Если он не найден, он выполняет поиск в предварительно настроенном списке стандартных системных каталогов.

Форма 2 - #include "xxx"

Это проверяет наличие заголовочного файла в текущем каталоге, из которого вызывается директива.


Точный список каталогов поиска зависит от целевой системы, от того, как настроен GCC и где он установлен. Вы можете найти список каталогов поиска вашего компилятора GCC, запустив его с параметром -v.

Вы можете добавить дополнительные каталоги к пути поиска, используя - Iреж, который заставляет искать каталог после текущего каталога (для формы цитаты директивы) и перед стандартными системными каталогами.


По сути, форма «xxx» - это не что иное, как поиск в текущем каталоге; если не найдено, откатить форму

Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения.

Jonathan Leffler 13.07.2019 08:27

@ Джонатан Леффлер. Можете ли вы указать мне на «хорошо обоснованный» ответ, который, по вашему мнению, столь же краток и точен, как ответ Даршана?

personal_cloud 13.07.2019 08:36

Описание формы #include "header.h" неточное, @personal_cloud. Я считаю, что ответ piCookie и Янн Дроно наиболее актуален, поскольку они определяют, откуда берется их информация. Я также не считаю, что ответ, получивший наибольшее количество голосов, полностью удовлетворительный.

Jonathan Leffler 13.07.2019 09:05

Почему этот ответ показан вверху, а два ответа ниже - один с более чем 650 голосами? Этот ответ меня смутил, потому что он не соответствует наблюдаемому мной поведению. Это может быть потому, что последнее предложение нарушено из-за того, что угловые скобки не используются. Я не уверен, что это должно означать.

Neonit 01.08.2019 18:37

Есть два способа написать инструкцию #include:

#include"filename"
#include<filename>

Значение каждой формы

#include"mylib.h"

Эта команда будет искать файл mylib.h в текущем каталоге, а также в указанном списке каталогов, как указано в пути поиска включения, который мог быть настроен.

#include<mylib.h>

Эта команда будет искать файл mylib.h только в указанном списке каталогов.

Путь поиска include - это не что иное, как список каталогов, в которых будет производиться поиск включаемого файла. Различные компиляторы C позволяют задавать путь поиска по-разному.

Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения.

Jonathan Leffler 13.07.2019 08:26

Чтобы увидеть порядок поиска в вашей системе с помощью gcc, в зависимости от текущей конфигурации, вы можете выполнить следующую команду. Вы можете найти более подробную информацию об этой команде здесь

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

Apple LLVM version 10.0.0 (clang-1000.10.44.2)
Target: x86_64-apple-darwin18.0.0
Thread model: 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 - -x c /dev/null
clang -cc1 version 10.0.0 (clang-1000.10.44.2) default target x86_64-apple-darwin18.0.0 ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/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 (framework directory)
End of search list.

#include <filename>

  • Препроцессор выполняет поиск в зависимости от реализации. Он сообщает компилятору искать каталог, в котором хранятся файлы системных заголовков.
  • Этот метод обычно используется для поиска стандартных файлов заголовков.

#include "filename"

  • Это указывает компилятору искать файлы заголовков, в которых выполняется программа. Если это не удалось, он ведет себя как #include <filename> и выполняет поиск в этом заголовочном файле там, где хранятся системные заголовочные файлы.
  • Этот метод обычно используется для идентификации определяемых пользователем файлов заголовков (файлов заголовков, которые создаются пользователем). Не используйте это, если вы хотите вызвать стандартную библиотеку, потому что она требует больше времени на компиляцию, чем #include <filename>.

#include <file> 

Включает файл, в котором используется каталог включения по умолчанию.

#include "file" 

Включает файл в текущий каталог, в котором он был скомпилирован.

В общем, разница в том, где препроцессор ищет файл заголовка:

#include - это директива препроцессора для включения файла заголовка. Оба #include используются для добавления или включения файла заголовка в программу, но сначала для включения файлов заголовков системы, а затем - для файлов заголовков, определенных пользователем.

  1. #include используется для включения файла заголовка системной библиотеки в программу, означает, что препроцессор C / C++ будет искать имя файла, в котором хранятся файлы библиотеки C или хранятся файлы предопределенных системных заголовков.
  2. #include "filename" is used to include user defined header file in the program, means the C/C++ preprocessor will search for the filename in the current directory the program is in and then follows the search path used for the #include

Проверьте документы gcc gcc включают файлы

"" будет искать ./ в первую очередь. затем найдите путь включения по умолчанию. вы можете использовать такую ​​команду, чтобы распечатать путь включения по умолчанию:

 gcc -v -o a a.c

вот несколько примеров, чтобы прояснить ситуацию: код a.c работает

// a.c
#include "stdio.h"
int main() {
        int a = 3;
        printf("a = %d\n", a);
        return 0;

}

код b.c тоже работает

\ b.c
#include <stdio.h>
int main() {
        int a = 3;
        printf("a = %d\n", a);
        return 0;

}

но когда я создаю новый файл с именем stdio.h в текущем каталоге

// stdio.h
inline int foo()
{
        return 10;
}

a.c вызовет ошибку компиляции, но b.c все еще работает

и "" могут использоваться вместе с одним и тем же именем файла. поскольку приоритет пути поиска другой. так что d.c тоже работает

// d.c
#include <stdio.h>
#include "stdio.h"
int main()
{
        int a = 0;

        a = foo();

        printf("a=%d\n", a);

        return 0;
}

~

Другие вопросы по теме