В чем разница между использованием угловых скобок и использованием кавычек в include
выражении в языках программирования C и C ++ , как показано ниже?
#include <filename>
#include "filename"
В чем разница между использованием угловых скобок и использованием кавычек в include
выражении в языках программирования C и C ++ , как показано ниже?
#include <filename>
#include "filename"
Ответы:
На практике разница заключается в том, где препроцессор ищет включенный файл.
Для #include <filename>
поиска препроцессора в зависимости от реализации, обычно в каталогах поиска, предварительно назначенных компилятором / IDE. Этот метод обычно используется для включения стандартных заголовочных файлов библиотеки.
Для #include "filename"
препроцессор поисков первых в том же каталоге, что и файл , содержащий директиву, а затем следует по пути поиска , используемый для#include <filename>
формы. Этот метод обычно используется для включения файлов заголовков, определенных программистом.
Более полное описание доступно в документации GCC по путям поиска .
#include <...>
использовал пакет, установленный в системе, и #include "..."
версию соседнего репозитория. Я мог бы иметь это задом наперед. В любом случае, защита включения в упакованном заголовке имеет префикс подчеркивания. (Это может быть соглашение о пакетах или способ преднамеренно предотвратить смешивание двух, хотя для меня было бы лучше иметь смысл классификаторы версий.)
Единственный способ узнать это - прочитать документацию вашей реализации.
В стандарте 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 "file"
форма используется, реализация сначала ищет файл с заданным именем, если это поддерживается. Если нет (поддерживается) или если поиск не удался, реализация ведет себя так, как если бы использовалась другая #include <file>
форма ( ).
Кроме того, существует третья форма, которая используется, когда #include
директива не соответствует ни одной из форм выше. В этой форме некоторая базовая предварительная обработка (например, расширение макроса) выполняется над «операндами» #include
директивы, и ожидается, что результат будет соответствовать одной из двух других форм.
<
и >
в качестве ключа для индексации в библиотеке.
Некоторые хорошие ответы здесь ссылаются на стандарт 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).
c99
- которая является именем POSIX для компилятора C. (Стандарт POSIX 2008 едва ли мог ссылаться на C11; обновление 2013 года для POSIX 2008 не изменило стандарт C, на который он ссылался.)
-L
.
Документация GCC говорит следующее о разнице между ними:
Как пользовательские, так и системные заголовочные файлы включены с использованием директивы предварительной обработки
‘#include’
. У него есть два варианта:
#include <file>
Этот вариант используется для системных заголовочных файлов. Он ищет файл с именем file в стандартном списке системных каталогов. Вы можете добавить каталоги к этому списку с помощью
-I
опции (см. « Вызов» ).
#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, поведение не определено.
#include "mypath/myfile"
не является эквивалентом #include "./mypath/myfile"
. Как говорится в ответе piCookie, двойные кавычки сообщают компилятору о поиске в соответствии с реализацией, что включает в себя поиск в указанных местах #include <...>
. (На самом деле, это, вероятно, эквивалентно, но только потому, что, например, его /usr/include/mypath/myfile
можно назвать /usr/include/./mypath/myfile
- по крайней мере, в Unix-подобных системах.)
defaultincludepaths
, а не дает другое значение .
(как указано выше). Это имеет ожидаемое последствие, что оба #include "..."
и #include <...>
ищут в dirpath
<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>
формы, если файл не найден. Остальное определяется реализацией.
-I
бизнес указан?
-I
.
#include <file.h>
сообщает компилятору о поиске заголовка в каталоге « file.h
include », например, для 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
каталог вашего компилятора.
По стандарту - да, они разные
Директива предварительной обработки вида
#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 утверждает, что порядок поиска зависит от конкретной реализации, что может усложнить переносимость. Что еще хуже, мы используем jam, который автоматически определяет местонахождение включаемых файлов. Вы можете использовать относительные или абсолютные пути для ваших включаемых файлов. т.е.
#include "../../MyProgDir/SourceDir1/someFile.hpp"
Более старые версии MSVS требовали двойной обратной косой черты (\\), но теперь это не требуется. Я не знаю, когда это изменилось. Просто используйте косую черту для совместимости с 'nix (Windows примет это).
Если вы действительно беспокоитесь об этом, используйте "./myHeader.h"
для включаемого файла в том же каталоге, что и исходный код (мой текущий, очень большой проект имеет несколько дублирующих имен включаемых файлов, разбросанных по всему - действительно проблема управления конфигурацией).
Вот пояснение MSDN, скопированное сюда для вашего удобства).
Цитируемая форма
Препроцессор ищет включаемые файлы в следующем порядке:
- В том же каталоге, что и файл, содержащий оператор #include.
- В каталоги открытых в данный момент включаемых файлов, в обратном порядке, в котором
они были открыты. Поиск начинается в каталоге родительского включаемого файла и
продолжается вверх по каталогам любых вложенных файлов дедушки и дедушки.- По пути, указанному каждой
/I
опцией компилятора.- По путям, указанным в
INCLUDE
переменной среды.Форма углового кронштейна
Препроцессор ищет включаемые файлы в следующем порядке:
- По пути, указанному каждой
/I
опцией компилятора.- Когда компиляция происходит в командной строке, по путям, указанным в
INCLUDE
переменной среды.
По крайней мере для версии GCC <= 3.0 форма угловых скобок не создает зависимости между включенным файлом и включающим файлом.
Поэтому, если вы хотите сгенерировать правила зависимости (используя опцию GCC -M для примера), вы должны использовать форму в кавычках для файлов, которые должны быть включены в дерево зависимостей.
Для #include ""
компилятора обычно выполняется поиск в папке файла, в которой содержатся включаемые, а затем и другие папки. Ибо #include <>
компилятор не ищет папку текущего файла.
<filename>
и другое и "filename"
ищет места, определенные реализацией.
Когда вы используете #include <filename>, препроцессор ищет файл в каталоге заголовочных файлов C \ C ++ (stdio.h \ cstdio, string, vector и т. Д.). Но, когда вы используете #include «filename»: сначала препроцессор ищет файл в текущем каталоге, а если его нет - ищет его в каталоге заголовочных файлов C \ C ++.
#include
директива обычная, она вообще не связана с файлами.
#Include с угловыми скобками будет искать «список мест, зависящий от реализации» (что очень сложно сказать «системные заголовки») для файла, который будет включен.
#Include с кавычками будет просто искать файл (и, "в зависимости от реализации", bleh). Это означает, что в обычном английском языке он будет пытаться применить путь / имя файла, который вы выбрасываете в нем, и не будет предварять системный путь или вмешиваться в него в противном случае.
Кроме того, если #include "" завершается неудачно, стандарт перечитывается как #include <>.
В документации по gcc есть (специфичное для компилятора) описание, которое, хотя и относится к gcc, а не к стандарту, намного проще для понимания, чем разговоры о стандартах ISO в стиле юриста.
zlib.h
в моих путях поиска «пользователя», и в пути поиска системы существует другая версия, тогда #include <zlib.h>
включает ли версию системы и #include "zlib.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 <>
для предопределенных заголовочных файловЕсли файл заголовка предопределен, вы просто пишете имя файла заголовка в угловых скобках, и это будет выглядеть так (при условии, что у нас есть предопределенное имя файла заголовка iostream):
#include <iostream>
#include " "
для заголовочных файлов программист определяетЕсли вы (программист) написали свой собственный файл заголовка, вы бы написали имя файла заголовка в кавычках. Итак, предположим, что вы написали заголовочный файл с именем myfile.h
, тогда это пример того, как вы будете использовать директиву include для включения этого файла:
#include "myfile.h"
Многие из ответов здесь сосредоточены на путях, которые компилятор будет искать, чтобы найти файл. Хотя это то, что делает большинство компиляторов, соответствующий компилятор может быть предварительно запрограммирован с эффектами стандартных заголовков и обрабатываться, скажем, #include <list>
как переключатель, и он вообще не должен существовать как файл.
Это не чисто гипотетически. Есть по крайней мере один компилятор, который работает таким образом. #include <xxx>
Рекомендуется использовать только со стандартными заголовками.
#include <abc.h>
используется для включения стандартных библиотечных файлов. Таким образом, компилятор проверит места, где находятся стандартные заголовки библиотеки.
#include "xyz.h"
скажет компилятору включить определенные пользователем заголовочные файлы. Таким образом, компилятор проверит наличие этих заголовочных файлов в текущей папке или -I
определенных папках.
В C ++ включить файл можно двумя способами:
Первый - #include, который указывает препроцессору искать файл в предопределенном местоположении по умолчанию. Это местоположение часто является переменной среды INCLUDE, которая обозначает путь для включения файлов.
И второй тип - #include «filename», который указывает препроцессору сначала искать файл в текущем каталоге, а затем искать его в предопределенных местоположениях, установленных пользователем.
Сначала ищет наличие заголовочного файла в текущем каталоге, откуда вызывается директива. Если не найден, выполняется поиск в предварительно сконфигурированном списке стандартных системных каталогов.
Это ищет наличие заголовочного файла в текущем каталоге, откуда вызывается директива.
Точный список каталогов поиска зависит от целевой системы, способа настройки GCC и места его установки. Вы можете найти список каталогов поиска вашего компилятора GCC, запустив его с опцией -v.
Вы можете добавить дополнительные каталоги в путь поиска, используя - I dir , который заставляет искать dir после текущего каталога (для формы директивы в кавычках) и перед стандартными системными каталогами.
По сути, форма «xxx» - это не что иное, как поиск в текущем каталоге; если не найдено, возвращаясь к форме
#include "header.h"
формы не точное, @personal_cloud. Я считаю ответ piCookie и Yann Droneaud наиболее актуальным, поскольку они определяют, откуда поступает их информация. Я не считаю, что голосование с наивысшим рейтингом также является полностью удовлетворительным.
#include <filename>
Используется , когда файловая система в настоящее время упоминается. Это заголовочный файл, который можно найти в системных местах по умолчанию, таких как /usr/include
или /usr/local/include
. Для ваших собственных файлов, которые должны быть включены в другую программу, вы должны использовать #include "filename"
синтаксис.
поиск <filename> в стандартных местах библиотеки C
тогда как «имя файла» ищет и в текущем каталоге.
В идеале вы должны использовать <...> для стандартных библиотек C и «...» для библиотек, которые вы пишете и присутствуют в текущем каталоге.
Простое общее правило заключается в использовании угловых скобок для включения заголовочных файлов, которые поставляются с компилятором. Используйте двойные кавычки, чтобы включить любые другие файлы заголовков. Большинство компиляторов делают это так.
1.9 - Заголовочные файлы объясняют более подробно о директивах препроцессора. Если вы начинающий программист, эта страница должна помочь вам понять все это. Я узнал об этом здесь, и я следил за этим на работе.
#include <filename>
используется, когда вы хотите использовать заголовочный файл системы C / C ++ или библиотеки компилятора. Этими библиотеками могут быть stdio.h, string.h, math.h и т. Д.
#include "path-to-file/filename"
используется, когда вы хотите использовать свой собственный файл заголовка, который находится в папке вашего проекта или где-то еще.
Для получения дополнительной информации о препроцессорах и заголовке. Читай С - Препроцессоры .
#include <filename>
#include "filename"
#include <filename>
и ищет этот заголовочный файл, где хранятся системные заголовочные файлы.#include <filename>
.Чтобы увидеть порядок поиска в вашей системе с помощью 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 (каталог платформы)
Конец списка поиска.
Существует два способа написать заявление #include. Это:
#include"filename"
#include<filename>
Смысл каждой формы
#include"mylib.h"
Эта команда будет искать файл mylib.h
в текущем каталоге, а также указанный список каталогов, как упомянуто во включенном пути поиска, который мог быть установлен.
#include<mylib.h>
Эта команда будет искать файл только mylib.h
в указанном списке каталогов.
Путь поиска для включения - это не что иное, как список каталогов, в которых будет выполняться поиск включаемого файла. Разные компиляторы C позволяют задавать путь поиска по-разному.