Какие каталоги включают поиск операторов в C / C ++? - PullRequest
3 голосов
/ 11 июня 2010

test.c:

#include "file.h"

В приведенном выше утверждении, какие каталоги будут искать?

Полагаю, будет найден каталог, в котором находится test.c, верно?

Но это все?

Кстати, в чем преимущество использования заголовочного файла? Java не требует заголовочный файл ...

Ответы [ 5 ]

8 голосов
/ 11 июня 2010
  • #include <header_name>: Стандартный включаемый файл: сначала посмотрите стандартные пути (настройка путей для компилятора системы)
  • #include "header_name": сначала поиск по текущему пути, затем по пути включения (пути поиска по проекту)

Преимущество использования файла заголовка состоит в том, чтобы предоставить другим интерфейс вашей библиотеки без реализации. Java не требует этого, потому что байт-код Java или jar может описать себя (рефлексия). Код C не может (пока) сделать это.

В Java вам понадобится только jar и правильный оператор использования. В C вам (в основном) понадобятся заголовок и файл lib (или header и dll).

Другая причина - способ компиляции кода c. Компилятор компилирует единицы перевода (файл c / cpp со всеми включенными заголовками), а компоновщик на втором шаге связывает весь материал. Объявления не должны компилироваться, это экономит время и позволяет избежать бесполезного генерирования кода для каждой единицы компиляции, которую компоновщик должен будет очистить.

Это просто общая идея, я не специалист по компилятору, но должен немного помочь.

2 голосов
/ 11 июня 2010

Это контролируется вашим компилятором.Например, у gcc есть опция -I для указания пути включения.

Требуются прототипы C и C ++, чтобы компилятор (отличный от компоновщика) мог убедиться, что функции вызываются с правильными аргументами.Java отличается тем, что компилятор использует двоичные файлы .class (которые, в отличие от C, имеют стандартный формат байт-кода с сохранением всей информации о типах), чтобы проверить, допустимы ли вызовы.

0 голосов
/ 11 июня 2010

Стандарт C ++ на самом деле не говорит, какие каталоги следует искать.Вот как стандарт C ++ описывает, что происходит, когда встречается #include "somefile.h":

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

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

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

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

с идентичной содержащейся последовательностью (включая> символы, если таковые имеются) из исходной директивы.

То есть, какие именно каталоги ищутся, зависят от вашей конкретной реализации C ++.

0 голосов
/ 11 июня 2010

strace или ферма и т. Д. Могут быть полезны. Например, создайте файл foo.c с одной строкой #include "foo.h". Затем на CYGWIN, команда:

strace /usr/bin/gcc-4.exe foo.c | grep 'src_path.*foo.h,' | sed 's/.*src_path //;s/foo.h.*//'

производит:

foo.c:1:22: error: foo.h: No such file or directory

/home/Joe/src/utilities/
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include-fixed/
/usr/include/
/usr/include/w32api/

Я был действительно удивлен, что этот список был настолько коротким: в последний раз, когда я делал это упражнение, в SunOS 4 пятнадцать лет назад, путь поиска имел более десятка каталогов.

Очевидно, что в первом каталоге находится foo.c. См. Также http://gcc.gnu.org/onlinedocs/cpp/Environment-Variables.html для переменных окружения CPATH и C_INCLUDE_PATH. Но они не установлены на моей машине. (И мне непонятно, использует ли их в любом случае CYGWIN.)

Редактировать: Самое простое решение - использовать cpp -v ( не gcc -v). Это дает:

COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=i686'
 /usr/lib/gcc/i686-pc-cygwin/4.3.4/cc1.exe -E -quiet -v -D__CYGWIN32__ -D__CYGWIN__ 
      -Dunix -D__unix__ -D__unix -idirafter /usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../..
       /include/w32api -idirafter 
       /usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/lib/../../include/w32api - 
       -mtune=generic -march=i686
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/include"
ignoring duplicate directory "/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/lib/../../include/w32api"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/i686-pc-cygwin/4.3.4/include
 /usr/lib/gcc/i686-pc-cygwin/4.3.4/include-fixed
 /usr/include
 /usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../include/w32api
End of search list.
0 голосов
/ 11 июня 2010

Использование кавычек после #include предписывает препроцессору искать включаемые файлы в том же каталоге файла, который содержит инструкцию #include, а затем в каталогах любых файлов, которые включают (#include) этот файл.Затем препроцессор выполняет поиск по пути, указанному параметром компилятора / I, а затем по путям, указанным в переменной среды INCLUDE.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...