Как компиляторы узнают, где найти #include ‹stdio.h›?

Мне интересно, как компиляторы в Mac OS X, Windows и Linux узнают, где найти заголовочные файлы C.

В частности, мне интересно, как он знает, где найти #include с скобками <>.

#include "/Users/Brock/Desktop/Myfile.h"    // absolute reference
#include <stdio.h>                         // system relative reference?

Я предполагаю, что в системе есть текстовый файл, с которым он консультируется. Откуда он знает, где искать заголовки? Можно ли изменить этот файл, если да, то где этот файл находится в операционной системе?


person Brock Woolf    schedule 14.12.2009    source источник
comment
Смотрите мой ответ на этот вопрос: я обновил его, и я думаю, что он должен работать для вас.   -  person Alok Singhal    schedule 14.12.2009
comment
Вы снова отредактировали свой пост, сделав мой комментарий непонятным. Вот о чем я говорю: stackoverflow.com/questions/ 1898837/   -  person Alok Singhal    schedule 14.12.2009
comment
@Alok Сейчас попробую, спасибо   -  person Brock Woolf    schedule 14.12.2009
comment
Это один из тех известных вопросов, могу ли я сделать X, где ответ должен быть, если вы должны спросить, вы не должны   -  person MSalters    schedule 14.12.2009


Ответы (6)


Когда компилятор собран, он знает о нескольких стандартных местах для поиска заголовочного файла. Некоторые из них не зависят от того, где установлен компилятор (например, /usr/include, /usr/local/include и т. д.), а некоторые зависят от того, где установлен компилятор (что для gcc контролируется --prefix при запуске configure).

Такие местоположения, как /usr/include, хорошо известны, и «знание» этого местоположения встроено в gcc. Такие расположения, как /usr/local/include, не считаются полностью стандартными и могут быть установлены при сборке gcc с опцией --with-local-prefix в configure.

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

person R Samuel Klatchko    schedule 14.12.2009

ОС не знает, где искать эти файлы — знает компилятор (точнее, препроцессор). У него есть набор путей поиска, по которым он знает, что нужно искать заголовки, подобно тому, как ваша командная оболочка имеет набор мест, где она будет искать программы для выполнения, когда вы вводите имя. Документация GCC объясняет, как это делает этот компилятор и как эти пути поиска могут быть изменен.

person Chuck    schedule 14.12.2009
comment
Голосуйте за хорошую информацию и хорошую ссылку на ресурс. Спасибо, Чак. - person bobby; 14.12.2009

Расположение файла зависит от системы. Действительно, файл может быть предварительно скомпилирован или даже не существовать. компилятор может иметь его как «встроенный». На моем макбуке я вижу, что такой файл есть в /usr/include/c++/4.2.1/iostream, но полагаться на него не стоит, и редактировать его определенно плохая идея.

person Alok Singhal    schedule 14.12.2009

В Visual Studio это либо в настройках проекта, если вы используете IDE, либо в переменной среды %INCLUDE%, если вы используете командную строку.

person Alex Budovski    schedule 14.12.2009

Если бы вы использовали g++, вы могли бы сделать что-то вроде этого, чтобы узнать, какие пути включения были найдены:

touch empty.cpp
g++ -v empty.cpp

Я не знаю, есть ли эквивалент для Xcode. Может быть, это сработает, поскольку Xcode основан на GCC?

person Dan    schedule 14.12.2009

Вам следует избегать #include файлов с использованием абсолютных путей. Компилятор ищет включаемые файлы в различных каталогах и включает файлы, начиная с каждого каталога. Например;

#include <boost/tokenizer.hpp>

Работает, потому что корневой каталог boost содержит папку с именем «boost», и эта папка либо находится в вашем пути включения по умолчанию, либо вы сделали что-то вроде этого.

g++ -I$BOOST_ROOT {blah,  blah}

Стандарт C и C++ заключается в том, что разделитель UNIX '/' будет работать одинаково для всех систем, независимо от того, что хост-система фактически использует для обозначения каталогов. Как уже упоминалось, иногда #include вообще не включает реальный файл.

person Chris Huang-Leaver    schedule 14.12.2009