Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C_Lect2.doc
Скачиваний:
2
Добавлен:
08.09.2019
Размер:
68.61 Кб
Скачать

5

Язык c. Лекция 2

1. Компиляция программы

1.1. Общая схема процесса получения выполняемой программы

Процесс создания выполняемого файла (т.е. программы в машинном коде) из исходного текста на языке C состоит из следующих шагов:

Зачем нужны два раздельных шага — компиляция и компоновка1 программы?

1. Стандартные библиотечные функции скомпилированы заранее и прилагаются к компилятору в виде объектных библиотек. Требуемые функции отыскиваются в библиотеках и присоединяются к программе на этапе сборки (компоновки). Поручать эту работу компилятору нерационально — он ориентирован на обработку исходного текста, тогда как объектные файлы и библиотеки содержат не текст, а двоичный машинный код. У компилятора и компоновщика (линкера) разная специализация — они имеют дело с информацией, представленной в принципиально отличных формах, и выполняют работу, непохожую по содержанию.

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

3. Программисты-профессионалы довольно часто пишут отдельные части программы на других языках (Фортране, Ассемблере и т.д.). Для каждого языка используется свой компилятор, а полученные объектные файлы связываются в единую исполняемую программу с помощью компоновщика. Объектный файл не содержит «языковой» специфики, поскольку он состоит в основном из машинных команд. Поэтому компоновщик (линкер) вполне может работать с объектными файлами от разных компиляторов.

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

1.2. Две фазы компиляции

Компиляция программы на языке C происходит в два этапа:

  1. Препроцессирование (предварительная обработка текста)

  2. Собственно компиляция (вообще говоря, тоже делится на две стадии — грамматический анализ и генерацию машинного кода).

Первая фаза выполняется препроцессором. Вначале из текста удаляются все комментарии. Затем препроцессор обрабатывает строки, начинающиеся с символа # — директивы препроцессора. К ним, в частности, относятся:

#include <имя-файла>

или

#include "имя-файла"

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

#define имя подставляемый-текст

Это директива макроподстановки в простейшей форме (бывает еще макроподстановка с параметрами; мы не будем пока ее рассматривать). Здесь имя — любое имя (идентификатор), т.е. последовательность букв и цифр, начинающаяся с буквы, а подставляемый-текст — любой текст без каких-либо ограничений (все, что находится в директиве после имени до конца строки). Если препроцессор находит имя в лежащем ниже тексте программы, он заменяет его на подставляемый текст. (Имя должно входить в текст как самостоятельный лексический элемент. Если имя является частью более длинного имени, то замена не производится. Не анализируется также содержимое текстовых констант.)

Препроцессор не анализирует грамматику и семантику (смысловое содержание) текста, он работает на уровне лексических элементов (т.е. умеет выделять в тексте отдельные «слова», но не интересуется смыслом этих слов).

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]