Единица трансляции
В недавнем прошлом на канале было много линковочной тематики. Соответственно это требует частого упоминания термина "единица трансляции" aka translation unit aka юнит. На канале много не нюхавшего прода народа, поэтому пришла в голову идея закрыть этот гештальт.
Вот вы изучаете плюсы. Долго и упорно. И сделали свой первый нетривиальный проект. И бежите радостный показывать его маме со словами: "Мама! Смотри, какую я программу написал.". И показываете ей, как ваши условные крестики-нолики работают. Это вы запустили исполняемый файл, который является результатом превращения вашего кода на с++ в машинный код. Но каким образом все многообразие файлов собирается в одну сущность? Как они между собой взаимодействуют для этого?
В рамках культуры разработки на С++ есть 2 принципиальных вида файлов: headers(заголовочные файлы)(.h|.hpp) и sources(файлы реализации)(.cxx|.cpp). Первые обычно предназначены для помещения в них сущностей, которые будут широко(или потенциально широко) использоваться в проекте. Вторые уже конкретно реализуют поведение этих сущностей. Ответ на вопросы: "Зачем такое разделение в принципе есть?" и "Зачем мы пишем множество файлов реализации?"- заслуживают отдельных постов. Просто примем за данность всем известный факт существования двух видов файлов.
Но на вход компилятора попадает только один тип файлов - sources(не будем касаться precompiled headers и сильно усложнять разговор). На самом деле компилятора может сожрать любой подходящий файл, просто так принято, что это .cpp файлы.
Стандартный source файл состоит из кучи заинклюженых заголовочников, возможно еще несколько видов директив препроцессора, типа #ifdef или #define и прочего, ну и, собственно, нашего кода. Когда такой файл пожирает компилятор, на самом деле первым в работу вступает препроцессор. Это такой предварительный обработчик файлов с кодом. В С и С++ есть несколько директив препроцессора, которые предназначены именно для этого обработчика. Он оперирует в основном текстом программы и фактически делает текстовые манипуляции. Например, директива #include"something.hpp" заменяется на полный текст файла something.hpp. Директива #define MAXARRAYSIZE 10 обозначает, что во всем файле строку MAXARRAYSIZE нужно заменить на 10. Причем 10 это будет прям строка в файле, это надо учитывать. Никакой проверки типов на этом этапе нет.
И вот файл, который получается после обработки исходника препроцессором называется единицей трансляции. То есть это базовый элемент компиляции С++ программы. Компилятор обрабатывает все единицы трансляции, превращая их в объектные файлы. И уже линкер собирает все эти объектные файлы в одну программу.
То есть и вправду не очень корректно говорить, что компилируются цппшники. Это делают все-таки единицы трансляции. Но я не оч понимаю людей, которые хейтят других за это, потому что просто культурой принято файлы реализации называть .cpp. А то, что там есть препроцессор - это и так понятно. Это понимает почти любой, кто писал #include <iostream>, а то есть почти все. Я уж преувеличиваю, но вы поняли мою мысль.
Divide et impera. Stay cool.
#compiler #cppcore
В недавнем прошлом на канале было много линковочной тематики. Соответственно это требует частого упоминания термина "единица трансляции" aka translation unit aka юнит. На канале много не нюхавшего прода народа, поэтому пришла в голову идея закрыть этот гештальт.
Вот вы изучаете плюсы. Долго и упорно. И сделали свой первый нетривиальный проект. И бежите радостный показывать его маме со словами: "Мама! Смотри, какую я программу написал.". И показываете ей, как ваши условные крестики-нолики работают. Это вы запустили исполняемый файл, который является результатом превращения вашего кода на с++ в машинный код. Но каким образом все многообразие файлов собирается в одну сущность? Как они между собой взаимодействуют для этого?
В рамках культуры разработки на С++ есть 2 принципиальных вида файлов: headers(заголовочные файлы)(.h|.hpp) и sources(файлы реализации)(.cxx|.cpp). Первые обычно предназначены для помещения в них сущностей, которые будут широко(или потенциально широко) использоваться в проекте. Вторые уже конкретно реализуют поведение этих сущностей. Ответ на вопросы: "Зачем такое разделение в принципе есть?" и "Зачем мы пишем множество файлов реализации?"- заслуживают отдельных постов. Просто примем за данность всем известный факт существования двух видов файлов.
Но на вход компилятора попадает только один тип файлов - sources(не будем касаться precompiled headers и сильно усложнять разговор). На самом деле компилятора может сожрать любой подходящий файл, просто так принято, что это .cpp файлы.
Стандартный source файл состоит из кучи заинклюженых заголовочников, возможно еще несколько видов директив препроцессора, типа #ifdef или #define и прочего, ну и, собственно, нашего кода. Когда такой файл пожирает компилятор, на самом деле первым в работу вступает препроцессор. Это такой предварительный обработчик файлов с кодом. В С и С++ есть несколько директив препроцессора, которые предназначены именно для этого обработчика. Он оперирует в основном текстом программы и фактически делает текстовые манипуляции. Например, директива #include"something.hpp" заменяется на полный текст файла something.hpp. Директива #define MAXARRAYSIZE 10 обозначает, что во всем файле строку MAXARRAYSIZE нужно заменить на 10. Причем 10 это будет прям строка в файле, это надо учитывать. Никакой проверки типов на этом этапе нет.
И вот файл, который получается после обработки исходника препроцессором называется единицей трансляции. То есть это базовый элемент компиляции С++ программы. Компилятор обрабатывает все единицы трансляции, превращая их в объектные файлы. И уже линкер собирает все эти объектные файлы в одну программу.
То есть и вправду не очень корректно говорить, что компилируются цппшники. Это делают все-таки единицы трансляции. Но я не оч понимаю людей, которые хейтят других за это, потому что просто культурой принято файлы реализации называть .cpp. А то, что там есть препроцессор - это и так понятно. Это понимает почти любой, кто писал #include <iostream>, а то есть почти все. Я уж преувеличиваю, но вы поняли мою мысль.
Divide et impera. Stay cool.
#compiler #cppcore