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

avatar
quest49
22 августа 2008 в 01:40
693818
31
2660

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

  1. #include <filename>
  2. #include "filename"
Источник
legends2k
5 июня 2013 в 10:40
16

gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC6

theoretisch
10 августа 2016 в 11:52
1

Где GCC ищет свои файлы заголовков

smwikipedia
17 марта 2020 в 05:58
0

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

Ответы (31)

avatar
david
9 июля 2021 в 04:14
1

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

Итак

#include <myFilename>

- который фактически объявляет, что myFilename находится в расположении системной библиотеки - вполне может (и, вероятно, будет) скрывать мертвый код, предупреждения о неиспользуемых переменных и т. Д., Которые будут отображаться при использовании:

#include "myFilename"

avatar
Paul Yang
27 февраля 2021 в 16:59
1

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

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;
}
avatar
Saptarshi das
24 ноября 2020 в 08:08
2

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

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

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

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

avatar
IAmAUser
1 марта 2020 в 23:11
1
#include <file> 

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

#include "file" 

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

avatar
Kalana
27 декабря 2019 в 05:18
5

#include <filename>

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

#include "filename"

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

Чтобы увидеть порядок поиска в вашей системе с помощью 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 InstalledDir: Library / Developer / CommandLineTools / usr / bin
"/ Библиотека / Разработчик / CommandLineTools / usr / bin / clang" -cc1 -triple x86_64-яблоко-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror = deprecated-objc-isa-usage -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning = lldb -target-linker-version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -I / usr / local / include -fdebug-compilation-dir / Users / hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime = macosx- 10.14.0 -fmax-type-align = 16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o - -xc / dev / null
clang -cc1 версия 10.0.0 (clang-1000.10.44.2) цель по умолчанию x86_64-apple-darwin18.0.0 игнорирование несуществующий каталог "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" игнорирование несуществующего каталога "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." поиск начинается здесь:
include <...> поиск начинается здесь:
/ usr / local / include
/Library/Developer/CommandLineTools/usr/lib/clang/10 / include
/ Library / Developer / CommandLineTools / usr / include
/Library/Developer/CommandLineTools/SDXDevelopment/CommandLineTools/SDXK10r/SDK10r / M / Sdk10r / M / S / DX-8 / M / S. >
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks (каталог инфраструктуры)
Конец списка поиска.

avatar
LocalHost
18 августа 2018 в 09:24
-3

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

#include"filename"
#include<filename>

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

#include"mylib.h"

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

#include<mylib.h>

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

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

Jonathan Leffler
13 июля 2019 в 05:26
1

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

avatar
Darshan L
17 августа 2018 в 09:59
6

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

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

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

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


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

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


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

Jonathan Leffler
13 июля 2019 в 05:27
3

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

personal_cloud
13 июля 2019 в 05:36
2

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

Jonathan Leffler
13 июля 2019 в 06:05
1

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

Neonit
1 августа 2019 в 15:37
1

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

avatar
Chayim Friedman
12 апреля 2018 в 06:36
15

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

IInspectable
2 октября 2018 в 19:31
1

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

Behrooz Karjoo
26 февраля 2019 в 20:06
2

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

IInspectable
13 июня 2021 в 07:02
0

@beh Этот ответ отлично справляется с этим.

avatar
jigar karangiya
28 марта 2018 в 11:35
5

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

, тогда как "filename" также выполняет поиск в текущем каталоге.

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

Daniel Langr
28 марта 2018 в 11:40
4

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

avatar
adrian
11 марта 2018 в 23:06
53

Точное поведение препроцессора зависит от компилятора. Следующий ответ относится к GCC и нескольким другим компиляторам.

#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 вашего компилятора.

Andrew
9 июля 2021 в 08:01
0

Перед этим ответом следует указать: «В некоторых реализациях (например, GCC) ...»

avatar
Christy Wald
23 января 2017 в 13:36
10
#include <abc.h>

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

#include "xyz.h"

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

avatar
Suraj Jain
14 января 2017 в 04:52
53

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

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

#include <file>

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

#include "file"

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

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

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

Jack M
30 июля 2020 в 13:31
0

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

Eljay
2 августа 2020 в 13:29
0

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

littleO
15 ноября 2020 в 00:56
0

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

avatar
virat
17 февраля 2016 в 09:07
7

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

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

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

avatar
skyking
18 августа 2015 в 06:21
24

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

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

    #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 <...> поиск по форме (путь включения, например, системные заголовки).

Kyle Strand
27 июля 2016 в 17:43
3

По большей части это тот же текст, что и ответ piCookie от семь лет ранее.

skyking
28 июля 2016 в 07:25
5

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

plugwash
11 сентября 2016 в 13:59
2

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

avatar
Hafiz Shehbaz Ali
2 апреля 2015 в 16:50
4
#include <filename>

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

#include "path-to-file/filename"

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

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

avatar
riderBill
14 октября 2014 в 23:51
19

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

Как и многие программисты, я использовал неформальное соглашение об использовании формы "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.
avatar
srsci
27 августа 2014 в 19:36
6

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

avatar
sp2danny
25 февраля 2014 в 10:49
13

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

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

supercat
15 марта 2021 в 21:02
0

Кстати, в Стандарте ничего не говорится ни о том, какие символы должна принимать реализация в именах файлов, ни о том, какие длины имен файлов должна принимать реализация. Соответствующая реализация может работать в файловой системе, в которой имена файлов ограничены шестью буквенно-цифровыми символами, и отклонять любые директивы формы #include "fname", в которых имя файла содержит точки, но соответствующая реализация должна принимать, например, `#include <float.h>` без учета того, будет ли float.h допустимым именем файла.

avatar
Eakan Gopalakrishnan
4 июня 2013 в 15:19
5

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

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

avatar
AndroidDev
17 декабря 2012 в 07:54
13
  • #include <> для предопределенных файлов заголовков

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

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

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

#include "myfile.h"
C Johnson
23 апреля 2019 в 15:29
2

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

avatar
Yann Droneaud
20 июля 2012 в 09:29
124

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

Согласно The Open Group Base Specifications 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).

osgx
12 марта 2015 в 02:34
1

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

Jonathan Leffler
10 ноября 2016 в 03:40
7

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

Pryftan
21 ноября 2019 в 22:55
1

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

avatar
Denis Ros
25 октября 2011 в 12:35
20

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

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

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

Pryftan
21 ноября 2019 в 23:01
1

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

avatar
Barbara
28 сентября 2011 в 20:37
11
#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"
avatar
Damon
8 февраля 2011 в 12:02
15

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

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

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

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

Loghorn
8 февраля 2011 в 12:59
0

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

the_mandrill
8 февраля 2011 в 13:10
0

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

the_mandrill
8 февраля 2011 в 13:10
0

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

Kyle Strand
27 июля 2016 в 17:45
0

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

avatar
Maxim Egorushkin
8 февраля 2011 в 11:45
18

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

Maxim Egorushkin
27 марта 2012 в 06:30
1

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

user3458
30 марта 2012 в 14:07
0

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

osvein
25 июля 2015 в 12:16
2

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

Maxim Egorushkin
17 сентября 2016 в 13:33
4

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

avatar
Stefan Steiger
8 февраля 2011 в 11:45
47

Имеет:

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

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

и

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

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

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

Keith Thompson
7 сентября 2011 в 23:03
16

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

Stefan Steiger
3 апреля 2014 в 09:23
1

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

Protongun
6 апреля 2014 в 18:07
1

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

Carlo Wood
27 сентября 2016 в 23:06
1

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

avatar
piCookie
16 сентября 2008 в 21:06
771

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

В стандарте 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: любой член исходного набора символов, кроме символа новой строки и "

Alexander Malakhov
10 октября 2012 в 03:48
117

Актуально: реализация в g ++ и в visual c ++

onmyway133
4 февраля 2013 в 03:45
32

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

piCookie
5 февраля 2013 в 16:38
5

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

Stefan
23 августа 2013 в 19:12
0

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

piCookie
25 августа 2013 в 00:22
16

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

Stefan
25 августа 2013 в 12:28
0

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

vargonian
29 апреля 2014 в 17:51
18

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

Rudy Velthuis
8 июня 2014 в 17:55
7

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

cloudcell
17 января 2015 в 13:12
5

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

anatolyg
29 марта 2015 в 19:32
158

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

Jacksonkr
4 мая 2016 в 13:45
4

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

Maxim Egorushkin
17 сентября 2016 в 13:32
9

"и <имя файла>, и" имя файла "ищут места, определенные реализацией". Чем полезен этот ответ на практике?

akhan
1 октября 2016 в 21:25
2

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

Dave Voyles
7 ноября 2016 в 19:00
5

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

osvein
15 июня 2017 в 12:44
11

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

Suma
8 июля 2018 в 07:18
0

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

SteamyThePunk
4 сентября 2018 в 17:36
8

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

Andrew
9 июля 2021 в 07:59
0

@Suma - вы должны помнить, что когда C был впервые стандартизирован, ему было уже 15+ лет, и разные реализации делали все по-разному ... эти различия были задокументированы как «реализация определяется»

avatar
aib
8 сентября 2008 в 17:43
313

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

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

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

Dan Moulding
17 августа 2009 в 16:12
55

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

Nav
27 января 2011 в 06:38
0

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

aib
27 января 2011 в 09:28
3

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

Maxim Egorushkin
8 февраля 2011 в 11:54
14

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

Dan Moulding
12 октября 2012 в 12:35
15

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

gnasher729
23 февраля 2014 в 20:55
1

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

supercat
15 августа 2015 в 17:57
2

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

Adrian McCarthy
15 февраля 2017 в 23:14
26

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

Wolf
11 декабря 2017 в 16:32
2

заголовок, который не обязательно является файлом - напоминает мне URL-адреса (в основном файлы в начале, а в наши дни все, что вы можете придумать)

avatar
user3458
3 сентября 2008 в 12:17
41

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

juanchopanza
28 декабря 2014 в 04:31
5

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

juanchopanza
28 декабря 2014 в 18:49
2

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

user3458
29 декабря 2014 в 14:40
2

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

mnr
1 июля 2021 в 08:24
0

«Все равно ищутся все направления, отличается только порядок поиска». Как может быть так, что если я попытаюсь скомпилировать свою программу с помощью mingw, если я включу его с помощью <>, он не сможет найти мой файл заголовка, но с помощью "" он его найдет.

avatar
quest49
22 августа 2008 в 01:40
1613

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

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

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

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

Richard Corden
17 сентября 2008 в 13:41
151

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

Dan Moulding
17 августа 2009 в 16:30
72

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

Gabriel Southern
12 марта 2012 в 21:49
5

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

0kcats
8 ноября 2017 в 20:46
11

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

John P
23 февраля 2018 в 00:21
1

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

Kamran Poladov
4 октября 2018 в 18:53
0

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

mckenzm
25 января 2019 в 09:21
0

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

paxdiablo
9 января 2020 в 23:58
2

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

Tilak Maddy
10 апреля 2020 в 07:56
0

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