В языках программирования C и С++ в чем разница между использованием угловых скобок и использованием кавычек в инструкции include
следующим образом?
-
#include <filename>
-
#include "filename"
В языках программирования C и С++ в чем разница между использованием угловых скобок и использованием кавычек в инструкции include
следующим образом?
#include <filename>
#include "filename"
На практике разница в том, где препроцессор выполняет поиск включенного файла.
Для #include <filename>
препроцессор выполняет поиск в зависимости от реализации, обычно в каталогах поиска, предварительно назначенных компилятором /IDE. Этот метод обычно используется для включения стандартных файлов заголовков библиотек.
Для #include "filename"
препроцессор ищет сначала в том же каталоге, что и файл, содержащий директиву, а затем следует путь поиска, используемый для формы #include <filename>
. Этот метод обычно используется для включения файлов заголовков, определенных программистом.
Более полное описание доступно в документации GCC на пути поиска.
Единственный способ узнать это - прочитать документацию по реализации.
В стандарте 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: любой элемент исходного набора символов, кроме символа новой строки и
"
Последовательность символов между < и > однозначно ссылаются на заголовок, который не обязательно является файлом. Реализации в значительной степени свободны использовать последовательность символов по своему усмотрению. (В основном, однако, просто рассматривайте его как имя файла и выполняйте поиск по пути include, так как остальные состояния сообщений.)
Если используется форма #include "file"
, реализация сначала ищет файл с заданным именем, если поддерживается. Если нет (поддерживается) или если поиск не выполняется, реализация ведет себя так, как если бы использовалась другая форма (#include <file>
).
Кроме того, существует третья форма и используется, когда директива #include
не соответствует ни одной из вышеперечисленных форм. В этой форме выполняется некоторая базовая предварительная обработка (например, расширение макросов) в "операндах" директивы #include
, и ожидается, что результат будет соответствовать одной из двух других форм.
Некоторые хорошие ответы здесь содержат ссылки на стандарт C, но забыли стандарт POSIX, особенно специфическое поведение команды c99 (например, C компилятор).
Согласно Исходные спецификации Open Group № 7,
-I
Измените алгоритм поиска заголовков, имена которых не являются абсолютными путями, чтобы посмотреть в каталоге, указанном по пути к каталогу, прежде чем искать в обычных местах. Таким образом, заголовки, имена которых заключены в двойные кавычки ( "), сначала выполняются поиск в каталоге файла со строкой #include, а затем в каталогах с именем -I, и последний в обычных местах. Для заголовков, имена которых заключены в угловые скобки (" < > "), заголовок следует искать только в каталогах, названных в параметрах -I, а затем в обычных местах. Каталоги, названные в параметрах -I, должны быть найдены в указанном порядке. Реализации должны поддерживать не менее десяти экземпляров этой опции в одном вызове команды c99.
Итак, в среде, совместимой с POSIX, с компилятором COS, совместимым с C, #include "file.h"
, скорее всего, будет искать ./file.h
во-первых, где .
- это каталог, где находится файл с инструкцией #include
в то время как #include <file.h>
, скорее всего, будет искать /usr/include/file.h
во-первых, где /usr/include
- ваша система определяет обычные места для заголовков (это не определено POSIX).
В документации GCC говорится о различии между ними:
Оба файла заголовка пользователя и системы включаются с помощью директивы предварительной обработки
'#include
. Он имеет два варианта:
#include <file>
Этот вариант используется для файлов системных заголовков. Он ищет файл с именем file в стандартном списке системных каталогов. Вы можете добавить каталоги в этот список с
-I
опции-I
(см. Invocation).
#include "file"
Этот вариант используется для файлов заголовков вашей собственной программы. Он ищет файл с именем file сначала в каталоге, содержащем текущий файл, затем в каталогах цитат, а затем в тех же каталогах, что и для
<file>
. Вы можете добавить каталоги в список каталогов цитат с-Iquote
. Аргумент'#include
, ограниченный кавычками или угловыми скобками, ведет себя как строковая константа в том, что комментарии не распознаются, а имена макросов не расширены. Таким образом,#include <x/*y>
указывает включение системного заголовочного файла с именемx/*y
.Однако, если обратные косые черты происходят внутри файла, они считаются обычными текстовыми символами, а не escape-символами. Обработаны ни одна из управляющих последовательностей символов, соответствующих строковым константам в C. Таким образом,
#include "x\n\\y"
указывает имя файла, содержащего три обратной косой черты. (Некоторые системы интерпретируют '\ как разделитель пути. Все это также интерпретирует'/
таким же образом. Наиболее портативно использовать только'/
.)Это ошибка, если есть что-либо (кроме комментариев) в строке после имени файла.
Он делает:
"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, поведение undefined.
<file>
include указывает препроцессору на поиск в каталогах -I
и в предопределенных каталогах first, а затем в каталоге .c file. "file"
include указывает препроцессору искать каталог исходного файла сначала, а затем возвращается к -I
и предопределен. В любом случае все адресаты обыскиваются, только порядок поиска отличается.
Стандарт 2011 года в основном обсуждает включенные файлы в "16.2 Ввод исходного файла".
2 Директива предварительной обработки формы
# include <h-char-sequence> new-line
выполняет поиск последовательности мест, определенных для реализации, для заголовка, однозначно идентифицированного указанную последовательность между < и > delimiters, и вызывает заменяя эту директиву всем содержимым заголовка. Как указаны места или идентифицирован заголовок от реализации.
3 Директива предварительной обработки формы
# include "q-char-sequence" new-line
вызывает замену этой директивы всем содержимым исходного файла, идентифицированного указанная последовательность между "разделителями". Именованный исходный файл поиск осуществляется в соответствии с реализацией. Если этот поиск не поддерживается, или если поиск не выполняется, директива перерабатывается как если он читает
# include <h-char-sequence> new-line
с идентичной содержащейся последовательностью (включая > символы, если они есть) из исходной директивы.
Обратите внимание, что форма "xxx"
ухудшается до формы <xxx>
, если файл не найден. Остальное определяется реализацией.
По стандарту - да, они разные:
Директива предварительной обработки формы
#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 <...>
поиск формы (включающий путь, например системные заголовки).
Спасибо за отличные ответы, особенно. Адам Стельмащик и ПиКуки и айб.
Как и многие программисты, я использовал неофициальное соглашение о использовании формы "myApp.hpp"
для конкретных приложений и формы <libHeader.hpp>
для системных файлов библиотеки и компилятора, то есть файлов, указанных в /I
и INCLUDE
переменная среды, в течение многих лет думая, что это стандарт.
Однако в стандарте C указано, что порядок поиска специфичен для реализации, что может сделать переносимость сложной. Хуже того, мы используем варенье, которое автоматически определяет, где находятся файлы include. Вы можете использовать относительные или абсолютные пути для ваших включенных файлов. то есть.
#include "../../MyProgDir/SourceDir1/someFile.hpp"
В старых версиях MSVS требуется двойная обратная косая черта (\\), но теперь это не требуется. Я не знаю, когда это изменилось. Просто используйте косые черты для совместимости с "nix (Windows примет это).
Если вы действительно беспокоитесь об этом, используйте "./myHeader.h"
для включенного файла в том же каталоге, что и исходный код (у моего текущего, очень большого проекта есть несколько дубликатов включенных имен файлов, разбросанных по-настоящему проблема управления конфигурацией).
Здесь объяснение MSDN скопировано здесь для вашего удобства).
Цитированная форма
Препроцессор выполняет поиск включенных файлов в следующем порядке:
- В том же каталоге, что и файл, содержащий оператор #include.
- В каталогах открытых файлов include в обратном порядке, в которых они были открыты. Поиск начинается в каталоге родительского файла include и
продолжается вверх по каталогам любого дедушки и бабушки, включая файлы.- По пути, указанному каждой опцией компилятора
/I
.- По пути, заданные переменной среды
INCLUDE
.Форма углового кронштейна
Препроцессор выполняет поиск включенных файлов в следующем порядке:
- По пути, указанному каждой опцией компилятора
/I
.- Когда компиляция выполняется в командной строке по путям, указанным переменной среды
INCLUDE
.
По крайней мере, для версии GCC <= 3.0 форма угловой скобки не создает зависимость между включенным файлом и включенным.
Итак, если вы хотите генерировать правила зависимостей (используя пример GCC -M для примера), вы должны использовать цитированную форму для файлов, которые должны быть включены в дерево зависимостей.
Для #include ""
компилятор обычно ищет папку с файлом, который содержит это, а затем другие папки. Для #include <>
компилятор не ищет текущую папку с файлом.
#include <file.h>
сообщает компилятору о поиске заголовка в его каталоге "includes", например, для MinGW компилятор будет искать file.h
в C:\MinGW\include\или везде, где установлен ваш компилятор.
#include "file"
сообщает компилятору, чтобы он искал текущий каталог (то есть каталог, в котором находится исходный файл) для file
.
Вы можете использовать флаг -I
для GCC, чтобы сообщить, что, когда он встречает include с угловыми скобками, он также должен искать заголовки в каталоге после -I
. GCC будет относиться к директории после флага, как если бы это был includes
каталог.
Например, если у вас есть файл myheader.h
в вашем собственном каталоге, вы можете сказать #include <myheader.h>
если вы вызвали GCC с флагом -I.
(указывая, что он должен искать для включения в текущий каталог.)
Без флага -I
вам нужно будет использовать #include "myheader.h"
для включения файла или переместить myheader.h
в каталог include
вашего myheader.h
.
Когда вы используете #include <filename>, предварительный процессор ищет файл в каталоге файлов заголовков C\C++ (stdio.h\cstdio, строка, вектор и т.д.). Но при использовании #include "filename": во-первых, предварительный процессор ищет файл в текущем каталоге, а если его нет, он ищет его в каталоге файлов заголовков C\C++.
Объект #include с угловыми скобками будет искать "список мест, зависящих от реализации" (это очень сложный способ сказать "заголовки системы" ) для файла, который будет включен.
#include с кавычками будет просто искать файл (и, "в зависимости от реализации", bleh). Это означает, что на обычном английском языке он попытается применить путь/имя файла, который вы набросите на него, и не будет добавлять системный путь или вмешаться в него в противном случае.
Кроме того, если #include "" не работает, он перечитывается как #include < > по стандарту.
gcc documentation имеет описание (специфичное для компилятора), которое, будучи специфичным для gcc, а не стандартным, намного легче понять, чем в адвокатском стиле по стандартам ISO.
#include <>
предназначен для предопределенных файлов заголовковЕсли файл заголовка предопределен, вы просто напишите имя файла заголовка в угловых скобках, и он будет выглядеть так (если у нас есть предопределенное имя файла заголовка iostream):
#include <iostream>
#include " "
для файлов заголовков, которые программист определяет Если вы (программист) написали свой собственный заголовочный файл, вы должны написать имя файла заголовка в кавычках. Итак, предположим, вы написали заголовочный файл с именем myfile.h
, то это пример того, как вы должны использовать директиву include, чтобы включить этот файл:
#include "myfile.h"
#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"
Многие из ответов здесь сосредоточены на путях, которые компилятор будет искать, чтобы найти файл. В то время как это делает большинство компиляторов, соответствующему компилятору разрешается предварительно запрограммировать эффекты стандартных заголовков и рассматривать, скажем, #include <list>
как коммутатор, и он вообще не должен существовать как файл.
Это не является чисто гипотетическим. Существует, по крайней мере, один компилятор, который работает именно так. Рекомендуется использовать #include <xxx>
только со стандартными заголовками.
#include <abc.h>
используется для включения стандартных файлов библиотек. Таким образом, компилятор будет проверять места, где находятся стандартные заголовки библиотек.
#include "xyz.h"
сообщит компилятору о включении пользовательских файлов заголовков. Поэтому компилятор проверяет эти файлы заголовков в текущей папке или -I
определенных папках.
В С++ включите файл двумя способами:
Первый - #include, который сообщает препроцессору искать файл в предопределенной папке по умолчанию. Это местоположение часто является переменной среды INCLUDE, которая обозначает путь для включения файлов.
И второй тип: #include "filename", который сообщает препроцессору сначала искать файл в текущем каталоге, а затем искать его в предопределенных местах, которые пользователь настроил.
поиск "<filename>" в стандартных ячейках библиотеки C
тогда как "filename" также ищет в текущем каталоге.
В идеале вы бы использовали <...> для стандартных библиотек C и "..." для библиотек, которые вы пишете и присутствуют в текущем каталоге.
#include <filename>
используется при обращении к системному файлу. Это файл заголовка, который можно найти в местах по умолчанию, таких как /usr/include
или /usr/local/include
. Для ваших собственных файлов, которые необходимо включить в другую программу, вы должны использовать синтаксис #include "filename"
.
Простым общим правилом является использование угловых скобок для включения файлов заголовков, которые поставляются вместе с компилятором. Используйте двойные кавычки для включения любых других файлов заголовков. Большинство компиляторов делают это таким образом.
1.9 - Заголовочные файлы более подробно объясняют предпроцессорные директивы. Если вы новичок-программист, эта страница поможет вам понять все это. Я узнал об этом здесь, и я слежу за ним на работе.
#include <filename>
используется, когда вы хотите использовать файл заголовка системы C/С++ или библиотек компилятора. Этими библиотеками могут быть stdio.h, string.h, math.h и т.д.
#include "path-to-file/filename"
используется, когда вы хотите использовать свой собственный файл заголовка, который находится в папке проекта или где-то еще.
Дополнительные сведения о препроцессорах и заголовке. Прочтите C - Препроцессоры.
Сначала ищет наличие заголовочного файла в текущем каталоге, откуда вызывается директива. Если он не найден, он выполняет поиск в предварительно настроенном списке стандартных системных каталогов.
Это ищет наличие заголовочного файла в текущем каталоге, откуда вызывается директива.
Точный список каталогов поиска зависит от целевой системы, способа настройки GCC и места его установки. Вы можете найти список каталогов поиска вашего компилятора GCC, запустив его с опцией -v.
Вы можете добавить дополнительные каталоги в путь поиска с помощью - Idir, который заставляет искать dir после текущего каталога (для формы директивы в кавычках) и перед стандартными системными каталогами.
По сути, форма "xxx" - это не что иное, как поиск в текущем каталоге; если не найдено, возвращаясь к форме
#include <filename> (1)
#include "filename" (2)
#include
включает исходный файл, идентифицируемый по имени файла, в текущий исходный файл в строке сразу после директивы.
Первая версия директивы ищет только стандартные каталоги включения. Стандартная библиотека C++, а также стандартная библиотека C неявно включены в стандартные каталоги include. Стандартные каталоги включения могут контролироваться пользователем через опции компилятора.
Вторая версия сначала ищет каталог, в котором находится текущий файл, и, только если файл не найден, ищет стандартные каталоги включения.
В случае, если файл не найден, программа не работает.
Чтобы увидеть порядок поиска в вашей системе с помощью 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: Библиотека/Разработчик /CommandLineTools/usr/bin
"/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Независимо -o bjc -I sa-usage -Werror = устарело -o bjc -I sa-usage -E -disable-free -disable-llvm -v erifier -discard -v alue-names -main-file-name null -mrelocation-model pic -pic-level 2 -mread-model posix -mdisable -fp -E lim -fno-strict-return -masm -v erbose -munwind-tables -target-cpu penryn -dwarf-column -I nfo -debugger-tuning = lldb -target-linker -v ersion 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 -E xtended-block-signature -fobjc-runtime = macosx-10.14.0 -fmax- type-align = 16 -fdiagnostics-show -o ption -fcolor-diagnostics -traditional-cpp -o - -x c/dev/null
clang -cc1 версия 10.0.0 (clang-1000.10.44.2) default target 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/локальные/включить
/Library/Developer/CommandLineTools/usr/lib/clang/10.0.0/include
/Library/Developer/CommandLineTools/USR/включать
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks (каталог фреймворка)
Конец списка поиска.
Существует два способа написания оператора #include. Это:
#include"filename"
#include<filename>
Значение каждой формы
#include"mylib.h"
Эта команда будет искать файл mylib.h
в текущем каталоге, а также указанный список каталогов, как упоминалось, n путь поиска, который может быть настроен.
#include<mylib.h>
Эта команда будет искать файл mylib.h
в указанном списке каталогов.
Путь поиска включает в себя только список каталогов, которые будут искать файл, который будет включен. Различные компиляторы C позволяют задавать путь поиска различными способами.
Ответ на simpel будет, когда вы используете #include "filename" в c, он ищет файл в текущем каталоге и в каталоге, где хранятся все остальные библиотеки, но в случае #include ищет файл только в директории где хранятся все библиотеки.
В основном мы используем #include "filename", когда хотим использовать некоторый файл, который был написан ранее, который мы хотим для текущего файла.
Answer-- Разница в том, где препроцессор ищет включенный файл.
Для #include "filename"
препроцессор ищет в том же каталоге, что и файл, содержащий директиву. Этот метод обычно используется для включения файлов заголовков, определенных программистом.
Для #include <filename>
препроцессор выполняет поиск в зависимости от реализации, обычно в каталогах поиска, предварительно назначенных компилятором /IDE. Этот метод обычно используется для включения стандартных заголовочных файлов библиотеки.
Я просто столкнулся с ситуацией, когда <> и "" имели большое значение (VS 2017).
У меня есть два проекта, "ABC" и "XYZ". Каждый из них использует разные предварительно скомпилированные заголовки, оба с именем " precomp.h
" (vg. \ABC\precomp.h
и \XYZ\precomp.h
).
Некоторые файлы CPP используются обоими проектами. Например, файл \ABC\MOD1.CPP
использует предварительно скомпилированный заголовок. Когда MOD1.CPP включен в XYZ, если я напишу это:
#include "precomp.h"
... он будет включать \ABC\precomp.h
(\ABC\precomp.h
из того же каталога, что и файл .CPP), что совершенно неверно.
Если я напишу:
#include <precomp.h>
он будет использовать \XYZ\precomp.h
, который является правильной версией заголовка.