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


2357

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

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



Для поведения Visual Studio, пожалуйста, проверьте: docs.microsoft.com/en-us/cpp/preprocessor/…
smwikipedia

Ответы:


1405

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

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

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

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


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

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

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

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

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

714

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

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

  • Директива предварительной обработки вида

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

    ищет последовательность выполнения определенных мест для заголовка определен однозначно указанной последовательностью между <и >разделителями, и приводит к замене этой Директивы всего содержимого заголовка . Как места определяются или как определяется заголовок, определяется реализацией.

  • Директива предварительной обработки вида

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

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

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

    с идентичной содержащейся последовательностью (включая >символы, если таковые имеются) из исходной директивы.

  • Директива предварительной обработки вида

    #include pp-tokens new-line

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

Определения:

  • h-char: любой элемент исходного набора символов, кроме символа новой строки и >

  • q-char: любой элемент исходного набора символов, кроме символа новой строки и "


108
Актуально: реализация в g ++ и в Visual C ++
Александр Малахов

27
@piCookie и <filename>, и "filename" ищут места, определенные реализацией. Так в чем же разница?
onmyway133

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

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

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

287

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

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

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


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

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

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

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

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

117

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

В соответствии с открытой базой спецификаций Group Issue 7 ,

-I каталог

Изменить алгоритм поиска заголовков , чьи имена не являются абсолютными путями, поиск в каталоге с именем в каталоге имя пути до поиска в обычных местах. Таким образом, заголовки, имена которых заключены в двойные кавычки (""), должны искать сначала в каталоге файла со строкой #include , затем в каталогах с именами в параметрах -I и, наконец, в обычных местах. Для заголовков, имена которых заключены в угловые скобки ("<>"), заголовок следует искать только в каталогах, указанных в параметрах -I , а затем в обычных местах. Каталоги, названные в -I опциях , должны быть найдены в указанном порядке.вызов команды c99 .

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


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

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

1
Это была моя первая мысль тоже. Manpage для gcc включает это, как и другие. Там также похожая вещь для библиотек -L.
Pryftan

50

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

Как пользовательские, так и системные заголовочные файлы включены с использованием директивы предварительной обработки ‘#include’. У него есть два варианта:

#include <file>

Этот вариант используется для системных заголовочных файлов. Он ищет файл с именем file в стандартном списке системных каталогов. Вы можете добавить каталоги к этому списку с помощью -Iопции (см. « Вызов» ).

#include "file"

Этот вариант используется для заголовочных файлов вашей собственной программы. Он ищет файл с именем file сначала в каталоге, содержащем текущий файл, затем в каталогах с цитатами и затем в тех же каталогах, для которых он используется <file>. Вы можете добавить каталоги в список каталогов котировок с помощью -iquoteопции. Аргумент ‘#include’, ограниченный ли кавычками или угловыми скобками, ведет себя как строковая константа, в которой комментарии не распознаются, а имена макросов не раскрываются. Таким образом, #include <x/*y>указывается включение системного заголовочного файла с именем x/*y.

Однако, если в файле происходит обратная косая черта, они считаются обычными текстовыми символами, а не экранирующими символами. Ни одна из escape-последовательностей символов, соответствующих строковым константам в C, не обрабатывается. Таким образом, #include "x\n\\y"указывается имя файла, содержащее три обратных слеша. (Некоторые системы интерпретируют '\' как разделитель пути. Все они также интерпретируются ‘/’одинаково. Он наиболее переносим для использования ‘/’.)

Это ошибка, если в строке после имени файла есть что-либо (кроме комментариев).


46

Оно делает:

"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, поведение не определено.


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

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

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

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

39

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

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

2 Директива предварительной обработки вида

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

ищет последовательность мест, определенных реализацией, для заголовка, уникально идентифицированного указанной последовательностью между разделителями <и>, и вызывает замену этой директивы всем содержимым заголовка. Как места определяются или как определяется заголовок, определяется реализацией.

3 Директива предварительной обработки вида

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

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

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

с идентичной содержащейся последовательностью (включая> символы, если таковые имеются) из исходной директивы.

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


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

1
Я не вижу ссылки на -I.
juanchopanza

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

28

#include <file.h>сообщает компилятору о поиске заголовка в каталоге « file.hinclude », например, для MinGW, который компилятор будет искать в 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каталог вашего компилятора.


22

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

  • Директива предварительной обработки вида

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

    ищет последовательность мест, определенных реализацией, для заголовка, уникально идентифицированного указанной последовательностью между < и >разделителями, и приводит к замене этой Директивы всего содержимого заголовка. Как места определяются или как определяется заголовок, определяется реализацией.

  • Директива предварительной обработки вида

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

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

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

    с идентичной содержащейся последовательностью (включая >символы, если таковые имеются) из исходной директивы.

  • Директива предварительной обработки вида

    #include pp-tokens new-line

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

Определения:

  • h-char: любой элемент исходного набора символов, кроме символа новой строки и >

  • q-char: любой элемент исходного набора символов, кроме символа новой строки и "

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

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


2
В основном это тот же текст, что и в ответе piCookie за семь лет до этого.
Кайл Стрэнд,

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

2
IMO, это лучший ответ здесь, потому что он охватывает и то, что говорит стандарт, и то, что фактически делает большинство компиляторов.
plugwash

17

Спасибо за отличные ответы, особенно Адам Стельмащик, ПиКуки и Аиб.

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

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

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

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

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

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

Цитируемая форма

Препроцессор ищет включаемые файлы в следующем порядке:

  1. В том же каталоге, что и файл, содержащий оператор #include.
  2. В каталоги открытых в данный момент включаемых файлов, в обратном порядке, в котором
    они были открыты. Поиск начинается в каталоге родительского включаемого файла и
    продолжается вверх по каталогам любых вложенных файлов дедушки и дедушки.
  3. По пути, указанному каждой /Iопцией компилятора.
  4. По путям, указанным в INCLUDEпеременной среды.

Форма углового кронштейна

Препроцессор ищет включаемые файлы в следующем порядке:

  1. По пути, указанному каждой /Iопцией компилятора.
  2. Когда компиляция происходит в командной строке, по путям, указанным в INCLUDEпеременной среды.

16

По крайней мере для версии GCC <= 3.0 форма угловых скобок не создает зависимости между включенным файлом и включающим файлом.

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

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


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

15

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


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

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

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

2
@Spookbuster Правильно, стандарт говорит и то <filename>и другое и "filename"ищет места, определенные реализацией.
Максим Егорушкин

14

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


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

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

11

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

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

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

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


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

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

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

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

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

10
  • #include <> для предопределенных заголовочных файлов

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

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

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

#include "myfile.h"

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

9

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

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


9
#include <abc.h>

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

#include "xyz.h"

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


7

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

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

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


7

Форма 1 - #include <xxx>

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

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

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


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

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


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


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

1
@Jonathan Leffler Можете ли вы указать мне на «хорошо обоснованный» ответ, который, по вашему мнению, является таким же кратким и точным, как и ответ Даршана?
personal_cloud

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

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

6

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


6

поиск <filename> в стандартных местах библиотеки C

тогда как «имя файла» ищет и в текущем каталоге.

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


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

5

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

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


4
#include <filename>

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

#include "path-to-file/filename"

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

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


3

#include <filename>

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

#include "filename"

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

2

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

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

Apple LLVM версия 10.0.0 (clang-1000.10.44.2)
Цель: x86_64-apple-darwin18.0.0
Модель потока: posix УстановленныйDir: Библиотека / Разработчик / CommandLineTools / usr / bin
"/ Библиотека / Разработчик / CommandLineTools / usr / bin / clang" -cc1-тройной x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-use -Werror = не рекомендуется-objc-isa-use -E -disable-free - отключить-llvm-верификатор -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-диагностика -traditional-cpp -o - -xc / dev / null
clang -cc1 версия 10.0.0 (clang-1000.10.44.2) цель по умолчанию x86_64-apple-darwin18.0.0 игнорирование несуществующего каталога "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" игнорирование несуществующего directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." поиск начинается здесь:
#include <...> поиск начинается здесь:
/ 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 (каталог платформы)
Конец списка поиска.


1
#include <file> 

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

#include "file" 

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


-2

Существует два способа написать заявление #include. Это:

#include"filename"
#include<filename>

Смысл каждой формы

#include"mylib.h"

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

#include<mylib.h>

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

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


1
Если вы решите ответить на более старый вопрос, на котором уже есть точные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакой пользы. Если у вас есть какая-то отличительная новая информация, или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию спустя долгое время после того, как вопрос был задан, обычно выигрывает ». Я не заработаю тебе много кредитов.
Джонатан Леффлер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.