Из GCC документов :
Заголовочные файлы служат двум целям.
- Системные заголовочные файлы объявляют интерфейсы для частей операционной системы.,Вы включаете их в свою программу для предоставления определений и объявлений, необходимых для вызова системных вызовов и библиотек.
- Ваши собственные заголовочные файлы содержат объявления для интерфейсов между исходными файлами вашей программы.Каждый раз, когда у вас есть группа связанных объявлений и определений макросов, все или большинство из которых необходимы в нескольких различных исходных файлах, рекомендуется создать для них файл заголовка.
Включение заголовкаfile дает те же результаты, что и копирование файла заголовка в каждый исходный файл, который в этом нуждается.Такое копирование будет трудоемким и подверженным ошибкам.С заголовочным файлом соответствующие объявления появляются только в одном месте.Если их необходимо изменить, они могут быть изменены в одном месте, и программы, которые включают файл заголовка, будут автоматически использовать новую версию при следующей перекомпиляции.Заголовочный файл исключает трудоемкость поиска и изменения всех копий, а также риск того, что невозможность найти одну копию приведет к несоответствиям внутри программы.
Я считаю, что заголовки C являются устаревшимиартефакты ранних дней C.
Важно понимать, что заголовки дословно включаются в исходные файлы препроцессором Си.Таким образом, на самом деле возникает вопрос: зачем нам нужно предварительное объявление?
Для того, чтобы сохранить исполняемые файлы небольшими, информация о типе не внедряется в объектный код, сгенерированный компиляторами Си.Из-за этого для связи с объектным файлом или библиотекой требуется определение типов, которые предоставляет каждая функция, так как эта информация недоступна из объектного файла.Современные компиляторы обходят это, проверяя исходный код или библиотеки на предмет определений. Идентификаторы и подписи извлекаются непосредственно из исходного кода или символов библиотеки.
Чтобы компиляторы были простыми и эффективными, было бынеуместно вводить определения проверок из библиотеки, с которой они будут связаны.Действительно, вполне допустимо скомпилировать файл без использованной библиотеки, даже если он недоступен на компьютере компиляции.Точно так же было бы обременительно откладывать компиляцию типа до тех пор, пока не будут скомпилированы его зависимости, и совершенно невозможно в случае циклических отношений.Для этого необходимо, чтобы сигнатура функции была доступна до ее использования (для проверки типа).Для удобства C по умолчанию равен int fun(...)
, так что в наиболее распространенном на тот момент случае необходимость в предварительном объявлении функций уменьшается.
Чтобы облегчить жизнь всем, ручные декларации былиделегирован препроцессору.По сути, компилятор C не имеет концепции заголовочного файла.Вместо этого объявления логически организованы в файлы заголовков, которые препроцессор добавляет в программу предварительной компиляции.
Это избавляет программиста от необходимости вводить все необходимые объявления в начале каждой единицы компиляции,но это, по сути, то, что происходит.
Все эти искажения на самом деле являются результатом ограничений, которые существовали в первые дни C.
Однако есть некоторые определенные преимущества, которые приводят кэти искажения.Доступность определений функций вне самого кода реализации позволяет четко разделить интерфейс и реализацию, что фактически позволяет создавать гораздо более чистые системы.В идеальном мире вам понадобится только заголовочный файл, чтобы использовать библиотеку без предварительного знания реализации.( в сторону: я обменяю вам идеальный мир на невидимого розового единорога, если вы когда-нибудь найдете его. )
Современные языки имеют конструкции более высокого уровня для отдельного интерфейса формы реализации: интерфейсы в Java, утка, в Python, Протоколы в Clojure, контракты в Эйфелевой и т. Д. *