2013-11-16 8 views
2

Когда вы включаете заголовочный файл (.h, .hpp, .hh, .hxx extensions) из C стандартной библиотеки или C++ STL (или даже включаете большой файл Microsoft, такой как windows.h) и используете только определенное ограниченное число функций из него, весь файл становится двоичным и копируется в исполняемый файл, или только определенные, соответствующие функции, которые используются, становятся бинарными?Как файл заголовка компилируется в исполняемый файл?

Если весь файл копируется (и это то, что я думаю, на самом деле происходит, поскольку windows.h имеет макроопределения для уменьшения избыточности, например, WIN32_LEAN_AND_MEAN) - почему так происходит? Почему команда препроцессора #include не копирует только используемые функции (и другие функции, которые используются этими функциями в фоновом режиме)? Разве это не экономически выгодно?

Если копируются только соответствующие функции - почему мы должны делать заголовок - включает в первую очередь? Почему бы нам не использовать только огромный набор функций, которые были бы использованы и скомпилированы при необходимости, например, ситуация в интерпретируемых языках, таких как PHP (и некоторые случаи в Python). Если это только потому, что «C и C++ старше и стандартизированы», почему бы не сделать это в своих новых версиях? или, по крайней мере, современные компиляторы, позволяющие это (мы уже видели случаи, когда компиляторы изгибают язык старения в пользу современного разработчика)?

ответ

3

Файл заголовка просто сообщает компилятору, какие типы внешних функций и переменных есть, определяет макросы, типы и т. Д. Ничто не копируется. Любые функции и переменные (так называемые внешние символы), на которые ссылаются в исходном файле, будут связаны во время фазы компоновщика.

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

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

+0

Итак, почему мы должны делать заголовок, включающий ** для стандартных библиотек **, в первую очередь? Почему это не пул стандартных функций (например, PHP)? Только из-за соображений компиляции? – Reflection

+2

Когда-то компиляторы были очень медленными. Кроме того, в C стандартная библиотека не отличается от любой пользовательской библиотеки. Файлы заголовков в основном присутствуют, чтобы сообщить компилятору, какие типы функций и переменные. Стандартная библиотека не имеет специального статуса – user1338

0

Состоит из сборника (кроме частей, защищенных #if, #ifdef и т. Д., Чтобы предотвратить его).

Как обычно, в C заголовки содержали только объявления не определения, за исключением макросов. Таким образом, компиляция заголовка в основном помещает имена в таблицу символов компилятора, не создавая никакого кода.

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

Это не значит, что весь контент попадает в окончательный исполняемый файл. Современный компоновщик делает совсем немного, чтобы объединить несколько определений одного и того же объекта/функции и устранить части, которые не используются.

Макросы, такие как WIN32_LEAN_AND_MEAN, были изобретены в первую очередь для улучшения времени компиляции. Обычно они практически не влияют на размер финального исполняемого файла.

0

Файлы заголовков не прочитаны непосредственно компилятором, вместо этого он считывается препроцессором, который в основном копирует его прямо в место директивы #include.

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

Возможно, вы захотите прочитать о the C preprocessor.

0

По моему опыту, файлы заголовков практически не имеют никакого отношения к размеру файла, поскольку почти все ОС имеют встроенный c или C++, и поэтому нет необходимости копировать двоичные файлы.

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

Если вы хотите получить больше информации, я также нашел, что это other Stack Overflow article.

Смежные вопросы