Подтвердить что ты не робот

Нужно ли компилировать файлы заголовков в программе на C?

Иногда я вижу, что кто-то компилирует программу на C следующим образом:

gcc -o hello hello.c hello.h

Как я знаю, нам просто нужно поместить файлы заголовков в программу на C, например:

#include "somefile"

и скомпилируйте программу C: gcc -o hello hello.c.

Когда нам нужно скомпилировать файлы заголовков или почему?

4b9b3361

Ответ 1

Во-первых, в общем случае:

Если эти файлы .h действительно типичные заголовочные файлы C-стиля (в отличие от того, что они совсем другие, которые просто называются с расширением .h), тогда нет, нет причин "компилировать" этот заголовок файлы независимо. Заголовочные файлы предназначены для включения в файлы реализации, а не для компилятора в качестве независимых единиц перевода.

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

В принципе, компиляция hello.h как самостоятельной единицы перевода эквивалентна созданию вырожденного файла dummy.c, состоящего только из директивы #include "hello.h" и подачи этого файла dummy.c компилятору. Он будет компилироваться, но это не будет иметь смысла.


Во-вторых, специально для GCC:

Многие компиляторы будут обрабатывать файлы по-разному в зависимости от расширения имени файла. GCC имеет специальное обращение к файлам с расширением .h, когда они поставляются компилятору в качестве аргументов командной строки. Вместо того, чтобы рассматривать его как обычный блок перевода, GCC создает предварительно скомпилированный файл заголовка для этого файла .h.

Вы можете прочитать об этом здесь: http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html

Итак, вот почему вы можете видеть файлы .h, которые напрямую передаются в GCC.

Ответ 2

Хорошо, давайте понять разницу между активным и пассивным кодом.

Активный код - это реализация функций, процедур, методов, то есть фрагментов кода, которые должны быть скомпилированы для исполняемого машинного кода. Мы храним его в файлах .c и уверены, что нам нужно его скомпилировать.

Пассивный код не выполняется сам, но ему нужно объяснить разные модули, как общаться друг с другом. Обычно файлы .h содержат только прототипы (заголовки функций), структуры.

Исключением являются макросы, которые формально могут содержать активные фрагменты, но вы должны понимать, что они используют на самом раннем этапе построения (предварительную обработку) с простой заменой. Во время компиляции макросы уже заменяются на ваш .c файл.

Другим исключением являются С++-шаблоны, которые должны быть реализованы в .h файлах. Но вот история похожа на макросы: они заменяются на ранней стадии (инстанцирование) и формально, друг друга - это другой тип.

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

Ответ 3

Мне кажется, нам нужен предварительный процесс (возможно, НЕ вызывать компиляцию) файла head. Потому что, по моему мнению, на этапе компиляции файл head должен быть включен в c файл. Например, в test.h мы имеем

typedef enum{
    a,
    b,
    c
}test_t

и в test.c мы имеем

void foo()
{
    test_t test;
    ...
}

во время компиляции, я думаю, что компилятор поставит код в файл head и c файл вместе, а код в файле head будет предварительно обработан и заменит код в c файле. Между тем, мы должны определить путь include в make файле.

Ответ 4

В некоторых системах попытки ускорить сбор полностью разрешенных ".c" файлов вызывают предварительную сборку включенных файлов "компиляция файлов заголовков". Тем не менее, это метод оптимизации, который не нужен для фактической разработки C.

Такой метод в основном вычислял операторы include и содержал кэш сглаженных. Обычно программная цепочка C рекурсивно будет вырезать и вставлять в включенные файлы, а затем передать весь объект компилятору. С предварительно скомпилированным кэшем заголовков цепочка инструментов проверяет, изменились ли какие-либо из входов (определений, заголовков и т.д.). Если нет, то он предоставит компилятору уже сплющенные фрагменты текстового файла.

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

Пока вам не нужна оптимизация компиляции, я настоятельно рекомендую избегать предварительной компиляции заголовков.