Открыть сервисСервис

Компиляция в программировании

Компиляция — это процесс преобразования исходного текста программы, написанного на языке программирования высокого уровня, в машинный код или иной промежуточный код, пригодный для непосредственного исполнения вычислительной системой. Компиляция относится к фундаментальным этапам жизненного цикла программного обеспечения и лежит в основе работы подавляющего большинства современных языков — от C и C++ до Rust, Go и Java. Программу, выполняющую такое преобразование, называют компилятором.

Общая характеристика

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

Компиляцию следует отличать от интерпретации. При интерпретации программа выполняется покомандно специальной программой-интерпретатором без предварительного порождения машинного кода. На практике границы размыты: многие современные среды (например, виртуальные машины Java или .NET) сочетают компиляцию в промежуточный байт-код с его последующей динамической компиляцией во время исполнения.

Этапы компиляции

Классический компилятор проходит несколько последовательных фаз.

Лексический анализ

Входной поток символов разбивается на лексемы — минимальные значимые единицы: идентификаторы, ключевые слова, числа, операторы. Эту фазу выполняет лексический анализатор (сканер).

Синтаксический анализ

Из последовательности лексем строится синтаксическое дерево, отражающее структуру программы согласно грамматике языка. Эту задачу решает синтаксический анализатор (парсер).

Семантический анализ

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

Генерация промежуточного кода

Программа переводится во внутреннее представление, не зависящее от конкретной архитектуры. Это упрощает оптимизацию и перенос компилятора на разные платформы.

Оптимизация

Промежуточный код преобразуется для повышения быстродействия и сокращения объёма: устраняются лишние вычисления, выполняется разворачивание циклов, распределение регистров.

Генерация машинного кода

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

Виды компиляторов

ПризнакВиды
Способ работыОднопроходные, многопроходные
Момент компиляцииСтатическая (до запуска), динамическая (JIT, во время работы)
Целевой кодВ машинный код, в байт-код, в другой язык (транспиляция)
НазначениеОптимизирующие, отладочные

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

Инструменты и технологии

Помимо самого компилятора, в цепочку построения программы входят препроцессор, ассемблер и компоновщик. Совокупность этих средств называют инструментальной цепочкой (toolchain). Широко известны компиляторы GCC, Clang, MSVC. Для языков с виртуальными машинами применяются javac и аналоги.

Историческую роль сыграл компилятор языка Фортран, созданный в 1950-х годах в IBM под руководством Джона Бэкуса. Он доказал, что автоматическая трансляция может порождать код, сопоставимый по эффективности с написанным вручную.

Значение

Компиляция обеспечивает переносимость программ: один и тот же исходный текст может быть откомпилирован для разных процессоров и операционных систем. Она также позволяет обнаруживать значительную часть ошибок ещё до запуска программы и открывает возможности для глубокой оптимизации, недостижимой при интерпретации. Именно компиляторы сделали возможным промышленное программирование на языках высокого уровня и развитие крупных программных систем.

Критика и ограничения

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

Источники: Ахо А., Лам М., Сети Р., Ульман Дж. «Компиляторы: принципы, технологии и инструменты»; Дейтел Х. «Программирование на C»; документация GNU Compiler Collection.