библиотеки - директива include c++




В чем разница между#include<filename> и#include "filename"? (20)

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

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

поиск «<filename>» в стандартных ячейках библиотеки C

тогда как «filename» также ищет в текущем каталоге.

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


#include <filename>

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

#include "path-to-file/filename"

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

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


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

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

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

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


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

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

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


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

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


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

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

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

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


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

В соответствии с базовыми спецификациями Open Group Issue 7 ,

-I каталог

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

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


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

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

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


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

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

    #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" для "./myHeader.h" файла в том же каталоге, что и исходный код (мой текущий, очень большой проект имеет несколько дубликатов включенных имен файлов, разбросанных по-настоящему - проблема управления конфигурацией ).

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

Цитированная форма

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

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

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

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

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

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

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

#include <file>

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

#include "file"

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

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

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


#include <filename>

найдет соответствующий файл из библиотеки C ++. это означает, что если у вас есть файл hello.h в папке библиотеки C ++, #include <hello.h>он загрузит его.

Но,

#include "filename"

найдет файл в том же каталоге, где находится ваш исходный файл.

К тому же,

#include "path_to_file/filename"

найдет файл в каталоге, в который вы ввели path_to_file.


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


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

#include"filename"
#include<filename>

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

#include"mylib.h"

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

#include<mylib.h>

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

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


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


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

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


Чтобы увидеть порядок поиска в вашей системе с помощью 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
"/ Библиотека / Разработчик / CommandLineTools / usr / bin / clang" -cc1 -triple x86_64-apple-macosx10.14.0 -Wdeprecated-objc-isa-use -Werror = устаревший-objc-isa-use -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 / Пользователи / 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 version 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 / local / include
/ Библиотека / Разработчик / CommandLineTools / usr / lib / clang / 10.0.0 / include
/ Библиотека / Разработчик / CommandLineTools / usr / include
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include
/ Библиотека / Разработчик / CommandLineTools / SDK / MacOSX10.14.sdk / System / Library / Frameworks (каталог фреймворка)
Конец списка поиска.


#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 <abc.h>

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

#include "xyz.h"

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





c-preprocessor