C: уточнение по переводу

Если у нас есть два файла.c и файл.h: main.c sub.c sub.h, где

main.c

#include "sub.h"
...

sub.c

#include "sub.h"
...

мы можем скомпилировать программу, либо я)

gcc -o a.out main.c sub.c

или ii)

gcc -c main.c
gcc -c sub.c
gcc -o a.out main.o sub.o

Учитывая этот случай, препроцессор выводит одну или две единицы перевода?

Я смущен, потому что: main.c включает в себя sub.hЭто означает, что препроцессор будет выводить один модуль компиляции. С другой стороны, созданы два объектных файла, main.o а также sub.oПрежде чем создавать исполняемый файл, я подумал, что "два исходных файла, таким образом, два блока перевода".

В какой части я недопонимаю? или где я делаю ошибки?

2 ответа

Решение

Вот что говорит об этом стандарт C:

Исходный файл вместе со всеми заголовками и исходными файлами, включенными в директиву предварительной обработки #include известен как блок обработки предварительной обработки. После предварительной обработки блок преобразования предварительной обработки называется блоком перевода. [..] Ранее переведенные единицы перевода могут быть сохранены индивидуально или в библиотеках. Отдельные блоки перевода программы связываются (например) вызовами функций, идентификаторы которых имеют внешнюю связь, манипулированием объектами, идентификаторы которых имеют внешнюю связь, или манипулированием файлами данных. Единицы перевода могут быть переведены отдельно, а затем соединены для создания исполняемой программы.

(Источник: проект стандарта C99, п. 5.1.1.1)

Таким образом, в обоих ваших случаях у вас есть две единицы перевода. Один из них происходит от предварительной обработки компилятором main.c и все, что включено через #include директивы, то есть sub.h и, вероятно, <stdio.h> и другие заголовки. Второе происходит от компилятора, который делает то же самое с sub.c,

Разница между первым и вторым примером заключается в том, что в последнем случае вы явно храните "разные переведенные единицы перевода" в виде объектных файлов.

Обратите внимание, что не существует правила, связывающего один объектный файл с любым количеством единиц перевода. Линкер GNU является одним из примеров компоновщика, который способен объединить два .o файлы вместе.

Стандарт, насколько я знаю, не определяет расширение исходных файлов. Несмотря на это, в практическом плане вы можете #include .c файл в другой, или поместив всю вашу программу в .h файл. С gcc Вы можете использовать опцию -x c заставить .h файл, который будет рассматриваться как отправная точка единицы перевода.

Различие сделано здесь:

Исходный файл вместе со всеми заголовками и исходными файлами, включенными в директиву предварительной обработки #include [...]

потому что заголовок не обязательно должен быть исходным файлом. Точно так же содержание <...> в #include директива не обязательно должна быть допустимым именем файла. Как именно компилятор использует именованные заголовки <...> а также "..." определяется реализацией.

Рассмотрим генерацию исполняемого файла как двухэтапный процесс: во-первых, каждый модуль перевода компилируется в объектный файл; давайте назовем это компилятором. Во-вторых, объектные файлы связаны вместе с исполняемой программой; давайте назовем это компоновщиком.

"Блок перевода" - это вопрос первого шага. Единицей перевода является каждый файл, с которого начинается компиляция (т. Е. Который передается компилятору). В большинстве IDE есть правила, которые объявляют, что каждый файл с расширением .c или же .cpp передается в качестве входных данных компилятору, тогда как другие файлы - нет. Так что файлы с расширением .h, .hpp, .txt обычно не передаются компилятору напрямую.

В вашем примере main.c а также sub.c вероятно, единицы перевода, тогда как sub.h не является самостоятельной единицей перевода (она только "включена" в другие единицы перевода и рассматривается в процессе их компиляции).

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

Обратите внимание, что даже .h файл может содержать полную программу; но если вы не настроите свою среду, что это .h-file скомпилирован сам по себе, он не будет генерировать объектный файл.

Другие вопросы по тегам