Питання Яка різниця між #include і #include "filename"?


На мовах програмування C та C ++ якою є різниця між використанням кутових дужок та використанням лапок у include викладення, наступне?

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

1813
2017-08-22 01:40


походження


gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC6 - legends2k
Де GCC дивиться, щоб знайти заголовки файлів - theoretisch


Відповіді:


На практиці різниця знаходиться в тому місці, де препроцесор шукає включений файл.

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

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

Більш повне опис доступне в GCC документація на шляхи пошуку.


1046
2017-08-22 01:40



Заява: "preprocessor шукає в тому ж каталозі ..." може бути правдою на практиці, але стандарт стверджує, що названий вихідний файл "шукається в певному порядку". Подивіться відповідь з piCookie. - Richard Corden
Хоча ваша відповідь може бути "вірною", тому що це скільки реалізацій працює за звичаєм, ви повинні уважно подивитися на відповіді AIB і piCookie. Вони обидва вказують (на підставі формулювання стандарту С), що реальною різницею є включення "заголовка" проти включення "вихідного файлу" (і ні, це не означає ".h" або "." c "). "Джерело" у цьому контексті може бути (і зазвичай, і майже завжди має бути) ".h" -файлом. Заголовок не обов'язково повинен бути файлом (компілятор може містити, наприклад, заголовок, який статично закодований, а не файл). - Dan Moulding
"... попередній процесор виконує пошук у тому самому каталозі, що і файл, який збирається для включення файлу". Це твердження не цілком правильне. Мені було цікаво це питання, тому що мені цікаво, що таке фактична відповідь, але я знаю, що це не так, бо, принаймні, з gcc, коли ви вкажете додатковий шлях включення з -I, який буде шукати файли, зазначені з #include "filename. ч " - Gabriel Southern
Ті, кому не подобається відповідь, будь ласка, наведіть один практичний приклад, де це неправильно. - 0kcats
Звичайно, я нещодавно змішував ці синтаксиси при включенні заголовків з "тієї ж" бібліотеки і в кінцевому підсумку з помилками переосмислення. Якщо я правильно зрозумів #include <...> використовував пакет, встановлений у системі та #include "..." використовувала суміжну версію репозиторію. Я можу мати тих назад. Так чи інакше, до складу заголовка, включеного до охоплення, входить заголовок підкреслення. (Це може бути конвенція для пакетів або, можливо, спосіб навмисно запобігти змішуванню цих двох, хоча кваліфікатори версії будуть для мене більш корисними.) - John P


Єдиний спосіб знати - прочитати документацію вашої реалізації.

В стандарт С, розділи 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 в директиві обробляються так само, як у звичайному тексті. (Кожен ідентифікатор, який наразі визначається як назва макросу, замінюється його замінним списком токенів попередньої обробки.) Директива, що виникла після всіх замін, повинна відповідати однієї з двох попередніх форм. Метод, за допомогою якого послідовність попередніх обробки токенів між a < і a > попередня обробка токенів пари або пари " символи об'єднуються в єдине ім'я заголовка токен попередньої обробки визначається за виконанням.

Визначення:

  • h-char: будь-який член вихідного набору символів, крім символу нового рядка та >

  • q-char: будь-який член вихідного набору символів, крім символу нового рядка та "


594
2017-09-16 21:06



Відповідні: реалізація в g ++ і в візуальна C ++ - Alexander Malakhov
@piCookie обидва <filename> та "filename" шукають місця, визначені для реалізації. Так яка різниця? - onmyway133
@Stefan, я просто цитую стандарт, який нічого не говорить про INCLUDE_PATH. Ваша реалізація може це зробити, і моя не може. Початкове запитання було в цілому C, а не спеціально gcc (що я не думаю, що використовує INCLUDE_PATH) або Microsoft C (який я думаю робить) або будь-який інший, тому на нього не можна відповісти загалом, але замість кожної документації впровадження має бути посилання на нього. - piCookie
Як і у всіх цих ситуаціях, конкретні приклади (особливо з загальних сценаріїв) дуже корисні і однаково оцінені. Зрозуміло, що брудні загальні відповіді не мають настільки практичного застосування. - vargonian
"Ось як стандарт C може бути багатослівним і не відповідати на ваше запитання" - anatolyg


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

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

Крім того, третя форма існує і використовується, коли #include Директива не відповідає жодній з форм вище. У цій формі деяка базова попередня обробка (наприклад, макророзширення) виконується на "операндах" #include директива, і результат має відповідати однієї з двох інших форм.


215
2017-09-08 17:43



+1, це, мабуть, найбільш коротка та правильна відповідь тут. Відповідно до стандарту (який piCookie цитує з його відповідей) єдиний реальний відмінність "заголовок" і "вихідний файл". Механізм пошуку визначається реалізацією в будь-якому випадку. Використання подвійних лапок означає, що ви маєте намір включити "вихідний файл", тоді як кутові дужки означають, що ви маєте намір включити "заголовок", який, як ви кажете, може не бути файлом взагалі. - Dan Moulding
Див. Коментар Дона Молдинга на відповідь quest49; стандартні заголовки не повинні бути у формі файлу, вони можуть бути вбудованими. - aib
Я читав ці "стандартні заголовки не потрібно бути у формі файлу" протягом десятиліття. Забезпечення реального прикладу? - Maxim Egorushkin
@ Максим Єгорушкін: Я також не можу думати про будь-які існуючі реальні приклади; однак, компілятор C11 не може існувати для MS-DOS, якщо заголовки не повинні бути файлами. Це пов'язано з тим, що деякі назви заголовків C11 несумісні з обмеженням імені файлу "8.3" MS-DOS. - Dan Moulding
@ МаксимЕгорушкін: Компілятор VAX / VMS C зберігав всі заголовки бібліотеки бібліотеки C в єдиному текстовому файлі бібліотеки (подібно до архіву unix), і використовував рядок між < і > як ключ для індексування в бібліотеку. - Adrian McCarthy


Деякі хороші відповіді тут посилаються на стандарт C, але забули стандарт POSIX, особливо специфіку поведінки c99 (наприклад, компілятор C) команда

Відповідно до Специфікації базової групи Open Issue 7,

  каталог

Змінити алгоритм пошуку заголовків, імена яких не є абсолютними шляхами, щоб шукати в каталозі, названому каталог Прізвисько перед тим як шукати в звичайних місцях. Таким чином, заголовки, імена яких вкладені в подвійні лапки (""), повинні бути першими в каталозі файлу з #включати line, потім в каталогах, названих в  варіанти, і останній в звичайних місцях. Для заголовків, імена яких вкладені в кутові дужки ("<>"), заголовок потрібно шукати лише в каталогах, зазначених у  варіанти, а потім у звичайних місцях. Каталоги, названі в  Опції повинні виконуватися у вказаному порядку. Реалізація повинна підтримувати щонайменше десять випадків цього варіанту в одному c99 виклик команди

Отже, в середовищі, сумісному з POSIX, з компілятором, сумісним із POSIX, #include "file.h" швидше за все, буде шукати ./file.h по-перше, де . це каталог, де знаходиться файл з #include заява, в той час як #include <file.h>, ймовірно, збирається шукати /usr/include/file.h по-перше, де /usr/include Ваша система визначена звичайні місця для заголовків (це, здається, не визначено POSIX).


92
2017-07-20 09:29



Яке точне джерело тексту? Це з нормативної частини IEEE Std 1003.1, 2013? - osgx
@osgx: ця формулювання (або щось надзвичайно схожий) міститься в специфікації POSIX для c99 - це ім'я POSIX для компілятора C. (Стандарт POSIX 2008 навряд чи може посилатися на C11, оновлення 2013 року POSIX 2008 не змінило стандарт C, про який він згадав.) - Jonathan Leffler


Це робить:

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

з . будучи або каталогом файлу, де #include міститься в, і / або поточному робочому каталозі компілятора та / або default_include_paths

і

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

Якщо ./ є в <default_include_paths>, то це не має значення.

Якщо mypath/myfile знаходиться в іншому каталозі включення, поведінка невизначена.


36
2018-02-08 11:45



Немає, #include "mypath/myfile" не є еквівалентом #include "./mypath/myfile". Як пише piCookie, двійні лапки дають компілятору можливість шукати за певним способом, що включає пошук у місцях, вказаних для #include <...>. (Насправді, це, ймовірно, еквівалентно, але тільки тому, що, наприклад, /usr/include/mypath/myfile можна називати як /usr/include/./mypath/myfile - принаймні на Unix-подібних системах.) - Keith Thompson
@ Кейт Томпсон: Це правильно, я думав про моє вікно Linux. Очевидно, це може бути різним. Хоча на практиці Windows як операційна система, що не використовує Posix, також інтерпретує / як розділювач шляхів, і /. Також існує. - Stefan Steiger
-L тріщина Опція потім додає тріщина до defaultincludepaths, на відміну від надання іншому значенню . (як зазначено вище). Це має очікувані наслідки для обох #include "..." і #include <...> шукати в тріщина - Protongun
Я думаю, ця відповідь невірна, оскільки вона означає, що заголовки, включені подвійними лапками, завжди шукаються в поточному робочому каталозі. Механізм пошуку є більш детальним; ця відповідь неповна. Я не додаю цей коментар, щоб поскаржитися або зіпсувати, але система просить мене додати коментар, щоб пояснити, чому я проголосував за цю відповідь. - Carlo Wood


Документація GCC говорить наступне про різницю між двома:

Обидва файли заголовків користувача та систем включені за допомогою директиви попередньої обробки ‘#include’. Вона має два варіанти:

#include <file>

Цей варіант використовується для файлів заголовків системи. Він шукає файл з назвою файла у стандартному списку системних каталогів. Ви можете додати каталоги до цього списку з -I варіант (див Виклик)

#include "file"

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

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

Це помилка, якщо в рядку після імені файлу є щось (крім коментарів).


30
2018-01-14 04:52





The <file> включає вказівку препроцесора для пошуку в -I каталоги та в заздалегідь визначених каталогах перший, потім у каталозі файлу .c. The "file" включає команду preprocessor для пошуку в каталозі вихідного файлу перший, а потім повернутися до -I і заздалегідь визначений. У будь-якому разі пошук здійснюється в усіх напрямках, лише порядок пошуку відрізняється.

У стандарті 2011 в основному обговорюються включені файли в "16.2 включення вихідного файлу".

2 Директива про попередню обробку форми

# include <h-char-sequence> new-line

виконує пошук послідовності визначених для реалізації місць для заголовка, визначеного унікально за допомогою   вказана послідовність між <і> розмежниками і викликає   заміна цієї директиви на весь вміст заголовка.   Як вказані місця або визначено заголовок   implementation-defined.

3 Директива про попередню обробку форми

# include "q-char-sequence" new-line

викликає заміну цієї директиви на весь вміст вихідного файлу, ідентифікованого   вказана послідовність між "розділювачами". Названий вихідний файл є   пошук здійснюється за певним способом виконання. Якщо це пошук   не підтримується, або якщо пошук не вдається, директива переробляється як   якщо він читатиметься

# include <h-char-sequence> new-line

з ідентичною міткою послідовності (включаючи> символи, якщо такі є) з оригінальної директиви.

Зауважте, що "xxx" форма погіршується до <xxx> якщо файл не знайдено. Решта - визначена реалізація.


23
2017-09-03 12:17



Не могли б ви навести посилання на те, де в стандарті C це -I бізнес вказаний? - juanchopanza
@ юанчопанза виконана Дивіться також верхню відповідь :) - Arkadiy
Я не бачу посилання на це -I. - juanchopanza
Це "визначена реалізацією" частина. - Arkadiy
Зітхає Я ваша відповідь, ви робите це звучить так, це щось вказане на мові. - juanchopanza


За стандартом - так, вони різні:

  • Директива про попередню обробку форми

    #include <h-char-sequence> new-line
    

    шукає послідовність визначених для реалізації місць для заголовка, визначеного однозначно за заданою послідовністю між < і > розділювачі та замінює цю директиву на весь вміст заголовка. Як вказані місця або визначено заголовок, визначено реалізацію.

  • Директива про попередню обробку форми

    #include "q-char-sequence" new-line
    

    викликає заміну цієї директиви на весь вміст вихідного файлу, ідентифікованого вказаною послідовністю між " розділювачі Названий вихідний файл шукається у визначеному для реалізації способі. Якщо цей пошук не підтримується, або якщо пошук не вдається, директива переробляється так, як вона читається

    #include <h-char-sequence> new-line
    

    з однаковою мірою послідовністю (включаючи > символи, якщо такі є) з оригіналу   директива

  • Директива про попередню обробку форми

    #include pp-tokens new-line
    

    (це не збігається з однією з двох попередніх форм). Прем'єр-обробка жетонів після include в директиві обробляються так само, як у звичайному тексті. (Кожен ідентифікатор, який наразі визначається як назва макросу, замінюється його замінним списком токенів попередньої обробки.) Директива, що виникла після всіх замін, повинна відповідати однієї з двох попередніх форм. Метод, за допомогою якого послідовність попередніх обробки токенів між a < і a > попередня обробка токенів пари або пари " символи об'єднуються в єдине ім'я заголовка токен попередньої обробки визначається за виконанням.

Визначення:

  • h-char: будь-який член вихідного набору символів, крім символу нового рядка та >

  • q-char: будь-який член вихідного набору символів, крім символу нового рядка та "

Зауважте, що стандарт не говорить ніякого відношення між способами реалізації. Перша форма виконується за одним способом виконання, а інша - за певним чином (можливо, іншим). Стандарт також вказує на наявність деяких включених файлів (наприклад, <stdio.h>)

Формально ви повинні прочитати посібник для вашого компілятора, однак зазвичай (за традицією) #include "..." форма шукає каталог файлу, у якому #include було знайдено спочатку, а потім директорії, що #include <...> пошукові форми (шлях включати, наприклад, заголовки системи).


16
2017-08-18 06:21



Це в основному такий самий текст, як і відповідь piCookie сім років раніше - Kyle Strand
@KyleStrand Це тому, що той самий текст є цитатою відповідного розділу в стандарті - цього тексту повинен бути однаковими. Фактична відповідь - не той самий текст і дещо інша - хоча я також визнаю, що вона буде написана в документації для реалізації. Я також зауважую, що це також трактується традиційним способом (що більшість або всі компілятори, я використовував з повагою) . - skyking
ІМО це найкраща відповідь тут, оскільки вона охоплює як стандарт говорить, так і те, що більшість компіляторів насправді. - plugwash