В чем разница между использованием угловых скобок и кавычек в операторе include в языках программирования C и C++, как показано ниже?
#include <filename>#include "filename"Чтобы узнать о поведении Visual Studio, проверьте: docs.microsoft.com/en-us/cpp/preprocessor/…





На практике разница заключается в том, где препроцессор ищет включенный файл.
Для #include <filename> препроцессор выполняет поиск в зависимости от реализации, обычно в каталогах поиска, предварительно назначенных компилятором / IDE. Этот метод обычно используется для включения файлов заголовков стандартной библиотеки.
Для #include "filename" препроцессор сначала выполняет поиск в том же каталоге, что и файл, содержащий директиву, а затем следует пути поиска, используемому для формы #include <filename>. Этот метод обычно используется для включения файлов заголовков, определенных программистом.
Более полное описание доступно в GCC документация по путям поиска.
Утверждение: «препроцессор ищет в том же каталоге ...» может быть верным на практике, но стандарт утверждает, что именованный исходный файл «ищется способом, определяемым реализацией». См. Ответ от piCookie.
Хотя ваш ответ может показаться «правдой», поскольку именно столько реализаций работают по соглашению, вам следует внимательно изучить ответы aib и piCookie. Они оба указывают (поддержанные формулировкой стандарта C), что реальное различие заключается в включении «заголовка» по сравнению с включением «исходного файла» (и нет, это не означает «.h» против «. c "). «Исходный файл» в этом контексте может быть (и обычно является и почти всегда должен быть) файлом «.h». Заголовок не обязательно должен быть файлом (компилятор может, например, включать статически закодированный заголовок, а не в файл).
«... препроцессор ищет в том же каталоге, что и компилируемый файл, файл, который нужно включить». Это утверждение не совсем верно. Меня заинтересовал этот вопрос, потому что мне было любопытно, каков фактический ответ, но я знаю, что это неправда, потому что, по крайней мере, с gcc, когда вы указываете дополнительный путь включения с -I, который будет искать файлы, указанные с #include "filename. час"
Тем, кому ответ не нравится, приведите, пожалуйста, один практический пример, где он неверен.
Конечно, недавно я смешал эти синтаксисы при включении заголовков из «той же» библиотеки и в итоге получил ошибки переопределения. Если я правильно понимаю, #include <...> использовал пакет, установленный в системе, а #include "..." использовал версию из ближайшего репозитория. Я мог бы сделать это наоборот. В любом случае, защита включения в упакованном заголовке имеет префикс подчеркивания. (Это может быть соглашение для пакетов или, может быть, способ намеренно предотвратить их смешивание, хотя квалификаторы версии будут для меня более понятными.)
Почему у некоторых пользователей Windows файл #includepch.h заключен в кавычки? Это не что-то вроде "определенного программистами" файла.
По сути, он позволяет «исправлять» включенное содержимое во время компиляции, чтобы «переопределить» обычный путь включения. Это предотвращает искажение чужого исходного (скажем, из библиотеки github) источника. Это очень распространено для библиотек и даже ядер Arduino.
«Один практический пример, когда это неправильно» не имеет значения. Стандарты существуют не зря. Рекомендация (в стандарте) - использовать <> для заголовков, включенных в реализацию, "" для всего остального. Но ясно, что это только руководство, пути поиска для обоих случаев определены реализацией, за исключением того факта, что "" вернется к <>, если он не может быть найден.
Обычно нормально нормально o:
<file> include указывает препроцессору искать в каталогах -I и в предварительно определенных каталогах первый, а затем в каталоге файла .c. "file" include сообщает препроцессору, что нужно выполнить поиск в каталоге первый исходного файла, а затем вернуться к -I и предопределенному. Все равно ищутся все направления, отличается только порядок поиска.
Стандарт 2011 года в основном обсуждает включаемые файлы в «16.2 Включение исходного файла».
2 A preprocessing directive of the form
# include <h-char-sequence> new-linesearches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.
3 A preprocessing directive of the form
# include "q-char-sequence" new-linecauses the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read
# include <h-char-sequence> new-linewith the identical contained sequence (including > characters, if any) from the original directive.
Обратите внимание, что форма "xxx" ухудшается до формы <xxx>, если файл не найден. Остальное определяется реализацией.
Не могли бы вы указать, где в стандарте C указывается этот бизнес -I?
Не вижу ссылки на -I.
Это часть, «определяемая реализацией».
Последовательность символов между однозначно относится к заголовку, который не обязательно является файлом. Реализации могут свободно использовать последовательность символов по своему усмотрению. (В большинстве случаев, однако, просто рассматривайте это как имя файла и выполняйте поиск в включить путь, как указано в других сообщениях.)
Если используется форма #include "file", реализация сначала ищет файл с заданным именем, если он поддерживается. Если не (поддерживается) или поиск завершается неудачно, реализация ведет себя так, как если бы использовалась другая (#include <file>) форма.
Кроме того, существует третья форма, которая используется, когда директива #include не соответствует ни одной из форм выше. В этой форме некоторая базовая предварительная обработка (такая как расширение макроса) выполняется для «операндов» директивы #include, и ожидается, что результат будет соответствовать одной из двух других форм.
+1, это, наверное, самый лаконичный и правильный ответ здесь. Согласно стандарту (который цитирует piCookie в своем ответе), единственное отличие настоящий - это «заголовок» и «исходный файл». В любом случае механизм поиска определяется реализацией. Использование двойных кавычек означает, что вы намереваетесь включить «исходный файл», а угловые скобки означают, что вы намереваетесь включить «заголовок», который, как вы говорите, может быть вовсе не файлом.
Я знаю, что спрашиваю об этом спустя много времени после того, как вы опубликовали ответ, но @aib, что вы имеете в виду под «уникальной ссылкой на заголовок, который не обязательно является файлом»? Даже заголовочные файлы - это файлы!
См. Комментарий Дэна Моулдинга к ответу quest49; стандартные заголовки не обязательно должны быть в виде файлов, они могут быть встроенными.
Я читал это «стандартные заголовки не обязательно должны быть в виде файлов» уже десять лет. Хотите привести реальный пример?
@ Максим Егорушкин: Я тоже не могу вспомнить ни одного существующего реального примера; однако полный компилятор C11 не может существовать для MS-DOS, если заголовки не обязательно должны быть файлами. Это связано с тем, что некоторые имена заголовков C11 несовместимы с ограничением имени файла MS-DOS «8.3».
Заголовки не обязательно являются файлами. Если вы напишете #include
@DanMoulding: компиляторы на основе MS-DOS, которые я видел, почти всегда интерпретируют #include "thisIsAVeryLongName.and.I.Love.Dots.h" as a request to read a file THISISAV.AND`; можно было бы выдать предупреждение, что имя в директиве не соответствует файлу; остальные, которые я видел, просто проигнорируют это. Не будет ли какой-либо из заголовков, необходимых для C11, работать в такой модели, например потому что два разных имени имеют общий префикс из 8 букв?
@MaximEgorushkin: Компилятор VAX / VMS C хранил все заголовки библиотеки времени выполнения C в одном текстовом файле библиотеки (аналогично архиву unix) и использовал строку между < и > в качестве ключа для индексации в библиотеке.
Единственный способ узнать это - прочитать документацию по вашей реализации.
В пунктах 2–4 раздела 6.10.2 стандарт C говорится:
A preprocessing directive of the form
#include <h-char-sequence> new-linesearches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the
<and>delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.A preprocessing directive of the form
#include "q-char-sequence" new-linecauses the replacement of that directive by the entire contents of the source file identified by the specified sequence between the
"delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read#include <h-char-sequence> new-linewith the identical contained sequence (including
>characters, if any) from the original directive.A preprocessing directive of the form
#include pp-tokens new-line(that does not match one of the two previous forms) is permitted. The preprocessing tokens after
includein the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms. The method by which a sequence of preprocessing tokens between a<and a>preprocessing token pair or a pair of"characters is combined into a single header name preprocessing token is implementation-defined.Definitions:
h-char: any member of the source character set except the new-line character and
>q-char: any member of the source character set except the new-line character and
"
Актуально: реализация в g ++ и в визуальный C++
@piCookie оба
@entropy: На таком форуме невозможно ответить на ваш вопрос. Ответ, который был бы правильным для одного конкретного компилятора, мог быть совершенно неправильным для другого. Каждая конкретная реализация / компилятор должна быть обязана разъяснять разницу, и это единственный надежный способ узнать. В нескольких других ответах приведены примеры, и, возможно, ваша реализация упоминается в одном из них.
@piCookie, но можно сказать, что угловые скобки проверяют INCLUDE_PATH, а "" - нет. Таким образом, угловые скобки представляют путь поиска, но вовсе не cwd. на самом деле нет никакой разницы, если вы уменьшите ее до точки, которая ищет только по стандартному пути включения.
@Stefan, я просто цитирую стандарт, в котором ничего не говорится о INCLUDE_PATH. Ваша реализация может это сделать, а моя - нет. Исходный вопрос был в общем C, а не конкретно gcc (который, я не думаю, использует INCLUDE_PATH) или Microsoft C (который, я думаю, использует) или любой другой, поэтому на него нельзя ответить в общем виде, но вместо этого необходимо ссылаться на документацию по каждой реализации.
@piCookie нет. INCLUDE_PATH больше предназначался как переменная, содержащая стандартные пути для компилятора, а не конкретная деталь реализации поставщика.
Как и во всех этих ситуациях, конкретные примеры (особенно общих сценариев) очень полезны и одинаково ценятся. Излишне тупые общие ответы не имеют такого практического применения.
Я точно не знаю, как это в C, но если я прочитал стандартную цитату выше, последовательность между < и > не обязательно должна быть именем файла. Подойдет все, что однозначно определяет заголовок. В C++ это означает, что
@ onmyway133 стандарт позволяет использовать механизмы поиска дваальтернатива. Если механизм поиска анальтернатива (для включают "") не реализован, включают "" функционирует как включают. Однако у этой цитаты из стандартов обязательно должно быть резюме - никому не нужно тратить время на выяснение того, что она подразумевает.
«Вот как стандарт C может быть многословным и не отвечать на ваш вопрос»
«Единственный способ узнать это - прочитать документацию по вашей реализации». Или спросив кого-нибудь на Stack Overflow. Я ценю, что вы выбрали «обучающий момент», но боюсь, что такое отношение быстро устаревает.
"оба
@MaximEgorushkin см. В комментарии Александра Малахова ссылки, описывающие реализацию для gcc и Visual C++. Аналогичная документация должна быть и для любого другого коммерческого компилятора. ИМО, комментарий Александра должен быть частью ответа.
Люди приходят сюда, чтобы им объяснили вещи в понятной для них манере. Простое указание на загадочную документацию бесполезно. Именно из-за этой плохой документации так многие из нас задаются этим вопросом.
@ DaveVoyles-MSFT, это единственный правильный ответ, потому что вопрос не указывал, какая реализация, а только «языки программирования C и C++». Как некоторые реализации обрабатывают #include, уже указывалось в комментариях, и это их место, потому что они на самом деле не ответят на вопрос.
Если ответ должен быть полезен, он должен указывать на предполагаемую цель и общее использование этих директив, а не только цитировать стандарт, в котором рассказывается, как вещи определены, но не объясняется, почему. Ответ должен включать тот факт, что используется для включения заголовков стандартной библиотеки, а "" используется для включения локальных включений проекта.
Целью цитирования стандарта является показать, что стандарт не дает ответа, так как разница, если таковая имеется, между этими двумя формами полностью зависит от реализации, поэтому цитирование стандарта предполагалось, предлагая вам прочитать свой соответствующая документация по реализации, потому что OP не указала, какова была их реализация. Проще говоря: стандартного ответа не существует, поэтому вы ДОЛЖНЫ проконсультироваться с соответствующей документацией по вашей реализации, чтобы выяснить это для вашего конкретного случая.
Оно делает:
"mypath/myfile" is short for ./mypath/myfile
где . является либо каталогом файла, в котором содержится #include, и / или текущим рабочим каталогом компилятора, и / или default_include_paths
и
<mypath/myfile> is short for <defaultincludepaths>/mypath/myfile
Если ./ находится в <default_include_paths>, это не имеет значения.
Если mypath/myfile находится в другом подключаемом каталоге, поведение не определено.
Нет, #include "mypath/myfile" не эквивалентен #include "./mypath/myfile". Как говорится в ответе piCookie, двойные кавычки говорят компилятору выполнять поиск в соответствии с определенным реализацией способом, который включает поиск в местах, указанных для #include <...>. (На самом деле, это, вероятно, эквивалентно, но только потому, что, например, /usr/include/mypath/myfile может называться /usr/include/./mypath/myfile - по крайней мере, в Unix-подобных системах.)
@Keith Thompson: Верно, я думал о своем Linux-компьютере. Видимо могло быть иначе. Хотя на практике Windows как операционная система, отличная от Posix, также интерпретирует / как разделитель путей, и ./ также существует.
опция -L dirpath затем добавляет dirpath к defaultincludepaths, вместо того, чтобы придавать другое значение . (как указано выше). Это имеет ожидаемые последствия, что и #include "...", и #include <...> будут искать в dirpath.
Я думаю, что этот ответ неверен, поскольку он подразумевает, что заголовки, заключенные в двойные кавычки, всегда ищутся в текущем рабочем каталоге. Механизм поиска более подробный; этот ответ неполный. Я добавляю этот комментарий не для того, чтобы жаловаться или хныкать, а потому, что система просит меня добавить комментарий, чтобы объяснить, почему я отклонил этот ответ.
Для #include "" компилятор обычно выполняет поиск в папке файла, который содержит это include, а затем в других папках. Для #include <> компилятор не выполняет поиск в папке текущего файла.
Не уверен, почему люди не согласны.
Я подозреваю, что это потому, что большинство людей компилируют только файлы в своем CWD. Если вы находитесь в каталоге foo, и вы компилируете foo / unittest / bar.c, и он включает bar.h, тогда "bar.h" работает и
@Maxim люди не согласны, потому что поведение, которое вы описываете, не является стандартным C.
@Spookbuster Верно, в стандарте говорится, что <filename> и "filename" ищут места, определенные реализацией.
#Include с угловыми скобками будет искать файл, который нужно включить, в «зависящем от реализации списке мест» (что является очень сложным способом сказать «системные заголовки»).
#Include с кавычками будет просто искать файл (и «в зависимости от реализации», bleh). Это означает, что на обычном английском языке он попытается применить путь / имя файла, которые вы ему укажете, и не будет добавлять системный путь в начале или вмешиваться в него в противном случае.
Кроме того, если #include "" не удается, он перечитывается как #include по стандарту.
документация gcc имеет (специфичное для компилятора) описание, которое, хотя и относится к gcc, а не к стандарту, намного проще для понимания, чем разговоры адвоката о стандартах ISO.
Однако использование угловых скобок или кавычек не влияет на способ включения файлов, это точно так же: препроцессор фактически создает большой исходный файл, копируя и вставляя код из включаемых файлов в исходный исходный файл, прежде чем дать это в компилятор (препроцессор выполняет другие действия, например #define sustitution, #if оценка и т. д., но обработка #include настолько проста)
А как насчет конфликтов? например, скажем, у меня есть zlib.h в моих «пользовательских» путях поиска, и другая версия существует в системном пути поиска, тогда #include <zlib.h> включает системную версию, а #include "zlib.h" включает мою собственную?
Ага, ответил на свой вопрос: stackoverflow.com/questions/21593/…
Благодарим вас за подтверждение того, что оба стандартных соглашения о реализации и имеют здесь значение, а не просто заявляют, что это неизвестно, потому что это не определено стандартом.
#include "filename" // User defined header
#include <filename> // Standard library header.
Пример:
Имя файла здесь Seller.h:
#ifndef SELLER_H // Header guard
#define SELLER_H // Header guard
#include <string>
#include <iostream>
#include <iomanip>
class Seller
{
private:
char name[31];
double sales_total;
public:
Seller();
Seller(char[], double);
char*getName();
#endif
В реализации класса (например, Seller.cpp и в других файлах, которые будут использовать файл Seller.h) теперь должен быть включен заголовок, определенный пользователем, как показано ниже:
#include "Seller.h"
По крайней мере, для версии GCC
Поэтому, если вы хотите сгенерировать правила зависимостей (например, используя опцию GCC -M), вы должны использовать цитируемую форму для файлов, которые должны быть включены в дерево зависимостей.
(См. http://gcc.gnu.org/onlinedocs/cpp/Invocation.html)
Да, есть несколько разных способов создания зависимостей. Это один из них, но не единственный.
Некоторые хорошие ответы здесь содержат ссылки на стандарт C, но забыли стандарт POSIX, особенно конкретное поведение команды c99 (например, компилятор C).
Согласно Базовые спецификации Open Group, выпуск 7,
-Idirectory
Change the algorithm for searching for headers whose names are not absolute pathnames to look in the directory named by the directory pathname before looking in the usual places. Thus, headers whose names are enclosed in double-quotes ( "" ) shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets ( "<>" ), the header shall be searched for only in directories named in -I options and then in the usual places. Directories named in -I options shall be searched in the order specified. Implementations shall support at least ten instances of this option in a single c99 command invocation.
Таким образом, в POSIX-совместимой среде с POSIX-совместимым компилятором C #include "file.h", вероятно, сначала будет искать ./file.h, где . - это каталог, в котором находится файл с оператором #include, а #include <file.h>, скорее всего, сначала будет искать /usr/include/file.h. , где /usr/include - это обычные места, определенный вашей системой для заголовков (похоже, не определен в POSIX).
Каков точный источник текста? Это из нормативной части IEEE Std 1003.1, 2013?
@osgx: эта формулировка (или что-то очень похожее) находится в спецификации POSIX для c99 - это имя POSIX для компилятора C. (Стандарт POSIX 2008 вряд ли может относиться к C11; обновление 2013 года до POSIX 2008 не изменило стандарт C, на который он ссылался.)
Это была и моя первая мысль. Справочная страница для gcc включает это, как и другие. То же самое и с библиотеками - -L.
#include <> предназначен для предопределенных файлов заголовковЕсли файл заголовка предопределен, вы просто должны написать имя файла заголовка в угловых скобках, и это будет выглядеть так (при условии, что у нас есть предопределенное имя файла заголовка iostream):
#include <iostream>
#include " " предназначен для файлов заголовков, определяемых программистом.Если бы вы (программист) написали свой собственный файл заголовка, вы бы написали имя файла заголовка в кавычках. Итак, предположим, вы написали заголовочный файл с именем myfile.h, тогда это пример того, как вы могли бы использовать директиву include для включения этого файла:
#include "myfile.h"
Это вообще не имеет ничего общего с предопределенными файлами заголовков. Это связано с местами, которые нужно искать.
Простое общее правило - использовать угловые скобки для включения файлов заголовков, поставляемых с компилятором. Используйте двойные кавычки для включения любых других файлов заголовков. Большинство компиляторов делают это именно так.
1.9 - Заголовочные файлы объясняет более подробно директивы препроцессора. Если вы начинающий программист, эта страница должна помочь вам во всем этом разобраться. Я узнал об этом отсюда и слежу за этим на работе.
Многие ответы здесь сосредоточены на путях, которые компилятор будет искать, чтобы найти файл. Хотя это то, что делают большинство компиляторов, соответствующий компилятор может быть предварительно запрограммирован с использованием эффектов стандартных заголовков и обрабатывать, скажем, #include <list> как переключатель, и он вовсе не обязательно должен существовать как файл.
Это не чисто гипотетическое. По крайней мере, один компилятор работает таким образом. Рекомендуется использовать #include <xxx> только со стандартными заголовками.
#include <filename> используется при обращении к системному файлу. Это файл заголовка, который можно найти в системных местоположениях по умолчанию, таких как /usr/include или /usr/local/include. Для ваших собственных файлов, которые необходимо включить в другую программу, вы должны использовать синтаксис #include "filename".
Спасибо за отличные ответы, особенно. Адам Стельмашчик и piCookie, и аиб.
Как и многие программисты, я использовал неформальное соглашение об использовании формы "myApp.hpp" для конкретных файлов приложения и формы <libHeader.hpp> для системных файлов библиотеки и компилятора, то есть файлов, указанных в /I и переменной среды INCLUDE, в течение многих лет считая, что это стандарт.
Однако в стандарте C указано, что порядок поиска зависит от реализации, что может затруднить переносимость. Что еще хуже, мы используем jam, который автоматически определяет, где находятся включаемые файлы. Вы можете использовать относительные или абсолютные пути для ваших включаемых файлов. т.е.
#include "../../MyProgDir/SourceDir1/someFile.hpp"
В более старых версиях MSVS требовалась двойная обратная косая черта (\\), но теперь это не требуется. Не знаю, когда это изменилось. Просто используйте косую черту для совместимости с 'nix (Windows примет это).
Если вас это беспокоит В самом деле, используйте "./myHeader.h" для включаемого файла в том же каталоге, что и исходный код (в моем текущем, очень большом проекте есть несколько повторяющихся имен включаемых файлов, разбросанных по сторонам - на самом деле проблема управления конфигурацией).
Вот Объяснение MSDN, скопированный сюда для вашего удобства).
Quoted form
The preprocessor searches for include files in this order:
- In the same directory as the file that contains the #include statement.
- In the directories of the currently opened include files, in the reverse order in which
they were opened. The search begins in the directory of the parent include file and
continues upward through the directories of any grandparent include files.- Along the path that's specified by each
/Icompiler option.- Along the paths that are specified by the
INCLUDEenvironment variable.Angle-bracket form
The preprocessor searches for include files in this order:
- Along the path that's specified by each
/Icompiler option.- When compiling occurs on the command line, along the paths that are specified by the
INCLUDEenvironment variable.
#include <filename>
используется, когда вы хотите использовать файл заголовка системы C / C++ или библиотек компилятора. Эти библиотеки могут быть stdio.h, string.h, math.h и т. д.
#include "path-to-file/filename"используется, когда вы хотите использовать свой собственный файл заголовка, который находится в папке вашего проекта или где-то еще.
Для получения дополнительной информации о препроцессорах и заголовке. Прочтите C - Препроцессоры.
По стандарту - да, разные:
A preprocessing directive of the form
#include <h-char-sequence> new-linesearches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the
<and>delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.A preprocessing directive of the form
#include "q-char-sequence" new-linecauses the replacement of that directive by the entire contents of the source file identified by the specified sequence between the
"delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read#include <h-char-sequence> new-linewith the identical contained sequence (including
>characters, if any) from the original directive.A preprocessing directive of the form
#include pp-tokens new-line(that does not match one of the two previous forms) is permitted. The preprocessing tokens after
includein the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after all replacements shall match one of the two previous forms. The method by which a sequence of preprocessing tokens between a<and a>preprocessing token pair or a pair of"characters is combined into a single header name preprocessing token is implementation-defined.Definitions:
h-char: any member of the source character set except the new-line character and
>q-char: any member of the source character set except the new-line character and
"
Обратите внимание, что в стандарте не говорится о какой-либо связи между способами, определяемыми реализацией. Первая форма выполняет поиск одним способом, определяемым реализацией, а другая (возможно, другим) способом, определяемым реализацией. Стандарт также указывает, что должны присутствовать определенные включаемые файлы (например, <stdio.h>).
Формально вам нужно прочитать руководство для вашего компилятора, однако обычно (по традиции) форма #include "..." выполняет поиск в каталоге файла, в котором сначала был найден #include, а затем в каталогах, которые ищет форма #include <...> (путь включения, например, системные заголовки).
В основном это тот же текст, что и ранее полученный ответ piCookie от семь лет.
@KyleStrand Это потому, что тот же текст является цитатой из соответствующего раздела в стандарте - этот текст должен должен быть идентичным. Фактический ответ - это не тот же текст и несколько отличается - хотя я также признаю, что он будет написан в документации для реализации, я также отмечаю, что существует также традиционный способ их интерпретации (что большинство или все компиляторы, которые я использовал, уважают) .
ИМО, это лучший ответ здесь, потому что он охватывает как то, что говорит стандарт, так и то, что на самом деле делают большинство компиляторов.
В C++ включить файл можно двумя способами:
Первый - #include, который указывает препроцессору искать файл в заранее определенном месте по умолчанию. Это расположение часто является переменной среды INCLUDE, которая указывает путь для включения файлов.
И второй тип - это #include «filename», который сообщает препроцессору, что сначала нужно искать файл в текущем каталоге, а затем искать его в заранее определенных местах, которые пользователь установил.
В документации GCC говорится следующее о разнице между ними:
Both user and system header files are included using the preprocessing directive
‘#include’. It has two variants:
#include <file>This variant is used for system header files. It searches for a file named file in a standard list of system directories. You can prepend directories to this list with the
-Ioption (see Invocation).
#include "file"This variant is used for header files of your own program. It searches for a file named file first in the directory containing the current file, then in the quote directories and then the same directories used for
<file>. You can prepend directories to the list of quote directories with the-iquoteoption. The argument of‘#include’, whether delimited with quote marks or angle brackets, behaves like a string constant in that comments are not recognized, and macro names are not expanded. Thus,#include <x/*y>specifies inclusion of a system header file namedx/*y.However, if backslashes occur within file, they are considered ordinary text characters, not escape characters. None of the character escape sequences appropriate to string constants in C are processed. Thus,
#include "x\n\y"specifies a filename containing three backslashes. (Some systems interpret ‘\’ as a pathname separator. All of these also interpret‘/’the same way. It is most portable to use only‘/’.)It is an error if there is anything (other than comments) on the line after the file name.
Что такое «каталог котировок»?
@JackM • имеется 3 места: Текущий каталог файла #include, каталоги котировок (пути для проверки стиля #include "foo.h" включают) и системные каталоги (пути для проверки стиля #include <bar.h>).
Что означает «система» во фразе «системный заголовочный файл»? Я обнаружил, что компьютерные ученые часто используют слово «система», и я часто не могу сказать, означает ли оно «операционная система», «компьютерная система» или что-то еще.
#include <abc.h>
используется для включения файлов стандартной библиотеки. Таким образом, компилятор проверит места, где находятся заголовки стандартных библиотек.
#include "xyz.h"
скажет компилятору включить определяемые пользователем файлы заголовков. Таким образом, компилятор проверит эти файлы заголовков в текущей папке или в папках, определенных -I.
#include <file.h> сообщает компилятору, что нужно искать заголовок в его «включаемом» каталоге, например для MinGW компилятор будет искать file.h в C: \ MinGW \ include \ или там, где установлен ваш компилятор.
#include "file" сообщает компилятору, что нужно искать file в текущем каталоге (т.е. в каталоге, в котором находится исходный файл).
Вы можете использовать флаг -I для GCC, чтобы сообщить ему, что, когда он встречает включение с угловыми скобками, он также должен искать заголовки в каталоге после -I. GCC будет обрабатывать каталог после флага, как если бы это был каталог includes.
Например, если у вас есть файл с именем myheader.h в вашем собственном каталоге, вы можете сказать #include <myheader.h>, если вы вызвали GCC с флагом -I . (что означает, что он должен искать включения в текущем каталоге).
Без флага -I вам придется использовать #include "myheader.h" для включения файла или переместить myheader.h в каталог include вашего компилятора.
the " < filename > " searches in standard C library locations
whereas "filename" searches in the current directory as well.
В идеале вы должны использовать <...>для стандартных библиотек C и "..." для библиотек, которые вы пишете и присутствуют в текущем каталоге.
Какая новая информация добавляет этот ответ к другим?
Когда вы используете #include
После того, как идеальный ответ был доступен в течение многих лет, зачем присылать его, ведь это явно неверно? Несмотря на то, что директива #include широко распространена, она вообще не связана строго с файлами.
@IInspectable, пожалуйста, объясните, почему это вообще не связано с файлами.
Сначала проверяет наличие заголовочного файла в текущем каталоге, откуда вызывается директива. Если он не найден, он выполняет поиск в предварительно настроенном списке стандартных системных каталогов.
Это проверяет наличие заголовочного файла в текущем каталоге, из которого вызывается директива.
Точный список каталогов поиска зависит от целевой системы, от того, как настроен GCC и где он установлен. Вы можете найти список каталогов поиска вашего компилятора GCC, запустив его с параметром -v.
Вы можете добавить дополнительные каталоги к пути поиска, используя - Iреж, который заставляет искать каталог после текущего каталога (для формы цитаты директивы) и перед стандартными системными каталогами.
По сути, форма «xxx» - это не что иное, как поиск в текущем каталоге; если не найдено, откатить форму
Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения.
@ Джонатан Леффлер. Можете ли вы указать мне на «хорошо обоснованный» ответ, который, по вашему мнению, столь же краток и точен, как ответ Даршана?
Описание формы #include "header.h" неточное, @personal_cloud. Я считаю, что ответ piCookie и Янн Дроно наиболее актуален, поскольку они определяют, откуда берется их информация. Я также не считаю, что ответ, получивший наибольшее количество голосов, полностью удовлетворительный.
Почему этот ответ показан вверху, а два ответа ниже - один с более чем 650 голосами? Этот ответ меня смутил, потому что он не соответствует наблюдаемому мной поведению. Это может быть потому, что последнее предложение нарушено из-за того, что угловые скобки не используются. Я не уверен, что это должно означать.
Есть два способа написать инструкцию #include:
#include"filename"
#include<filename>
Значение каждой формы
#include"mylib.h"
Эта команда будет искать файл mylib.h в текущем каталоге, а также в указанном списке каталогов, как указано в пути поиска включения, который мог быть настроен.
#include<mylib.h>
Эта команда будет искать файл mylib.h только в указанном списке каталогов.
Путь поиска include - это не что иное, как список каталогов, в которых будет производиться поиск включаемого файла. Различные компиляторы C позволяют задавать путь поиска по-разному.
Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения.
Чтобы увидеть порядок поиска в вашей системе с помощью gcc, в зависимости от текущей конфигурации, вы можете выполнить следующую команду. Вы можете найти более подробную информацию об этой команде здесь
cpp -v /dev/null -o /dev/null
Apple LLVM version 10.0.0 (clang-1000.10.44.2)
Target: x86_64-apple-darwin18.0.0
Thread model: posix InstalledDir: Library/Developer/CommandLineTools/usr/bin
"/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -E -disable-free -disable-llvm-verifier -discard-value-names -main-file-name null -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fno-strict-return -masm-verbose -munwind-tables -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 409.12 -v -resource-dir /Library/Developer/CommandLineTools/usr/lib/clang/10.0.0 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk -I/usr/local/include -fdebug-compilation-dir /Users/hogstrom -ferror-limit 19 -fmessage-length 80 -stack-protector 1 -fblocks -fencode-extended-block-signature -fobjc-runtime=macosx-10.14.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -traditional-cpp -o - -x c /dev/null
clang -cc1 version 10.0.0 (clang-1000.10.44.2) default target x86_64-apple-darwin18.0.0 ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/local/include" ignoring nonexistent directory "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/Library/Developer/CommandLineTools/usr/lib/clang/10.0.0/include
/Library/Developer/CommandLineTools/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks (framework directory)
End of search list.
#include <filename>
#include "filename"
#include <filename> и выполняет поиск в этом заголовочном файле там, где хранятся системные заголовочные файлы.#include <filename>.#include <file>
Включает файл, в котором используется каталог включения по умолчанию.
#include "file"
Включает файл в текущий каталог, в котором он был скомпилирован.
В общем, разница в том, где препроцессор ищет файл заголовка:
#include - это директива препроцессора для включения файла заголовка. Оба #include используются для добавления или включения файла заголовка в программу, но сначала для включения файлов заголовков системы, а затем - для файлов заголовков, определенных пользователем.
Проверьте документы gcc gcc включают файлы
"" будет искать ./ в первую очередь. затем найдите путь включения по умолчанию. вы можете использовать такую команду, чтобы распечатать путь включения по умолчанию:
gcc -v -o a a.c
вот несколько примеров, чтобы прояснить ситуацию: код a.c работает
// a.c
#include "stdio.h"
int main() {
int a = 3;
printf("a = %d\n", a);
return 0;
}
код b.c тоже работает
\ b.c
#include <stdio.h>
int main() {
int a = 3;
printf("a = %d\n", a);
return 0;
}
но когда я создаю новый файл с именем stdio.h в текущем каталоге
// stdio.h
inline int foo()
{
return 10;
}
a.c вызовет ошибку компиляции, но b.c все еще работает
и "" могут использоваться вместе с одним и тем же именем файла. поскольку приоритет пути поиска другой. так что d.c тоже работает
// d.c
#include <stdio.h>
#include "stdio.h"
int main()
{
int a = 0;
a = foo();
printf("a=%d\n", a);
return 0;
}
~