После компоновки программа на машинном языке сохраняется на диске в виде
Программа – это, прежде всего, текст на языке Си++. С помощью компилятора текст преобразуется в исполняемый файл – форму, позволяющую компьютеру выполнять программу.
На третьем этапе компиляции к объектному файлу подсоединяются все функции на которые он ссылается. Функции тоже должны быть скомпилированы, т.е. переведены на машинный язык в форму объектных файлов . Этот процесс называется компоновкой , и как раз его результат и есть исполняемый файл .
Системные функции и стандартные функции языка Си++ заранее откомпилированы и хранятся в виде библиотек . Библиотека – это некий архив объектных модулей, с которым удобно компоновать программу.
Основная цель многоэтапной компиляции программ – возможность компоновать программу из многих файлов . Каждый файл представляет собой законченный фрагмент программы, который может ссылаться на функции, переменные или классы, определенные в других файлах. Компоновка объединяет фрагменты в одну "самодостаточную" программу, которая содержит все необходимое для выполнения.
Проблема использования общих функций и имен
В языке Си++ существует строгое правило, в соответствии с которым прежде чем использовать в программе имя или идентификатор, его необходимо определить. Рассмотрим для начала функции. Для того чтобы имя функции стало известно программе, его нужно либо объявить, либо определить.
Объявление функции состоит лишь из ее прототипа, т.е. имени, типа результата и списка аргументов. Объявление функции задает ее формат, но не определяет, как она выполняется. Примеры объявлений функций:
Определение функции – это определение того, как функция выполняется. Оно включает в себя тело функции, программу ее выполнения.
Определение функции играет роль объявления ее имени, т.е. если в начале файла определена функция fact , в последующем тексте функций и классов ею можно пользоваться. Однако если в программе функция fact используется в нескольких файлах, такое построение программы уже не подходит. В программе должно быть только одно Определение функции .
Удобно было бы поместить Определение функции в отдельный файл, а в других файлах в начале помещать лишь объявление, прототип функции .
Компоновщик объединит оба файла в одну программу.
Аналогичная ситуация существует и для классов. Любой класс в языке Си++ состоит из двух частей: объявления и определения. В объявлении класса говорится, каков интерфейс класса, какие методы и атрибуты составляют объекты этого класса. Объявление класса состоит из ключевого слова class , за которым следует имя класса, список наследования и затем в фигурных скобках - методы и атрибуты класса. Заканчивается объявление класса точкой с запятой.
Определение класса – это определение всех его методов.
Определение класса должно быть только одно, и если класс используется во многих файлах, его удобно поместить в отдельный файл. В остальных файлах для того, чтобы использовать класс Book , например определить переменную класса Book , в начале файла необходимо поместить объявление класса.
Таким образом, в начале каждого файла будут сосредоточены прототипы всех используемых функций и объявления всех применяемых классов.
Программа работать будет, однако писать ее не очень удобно.
В начале каждого файла нам придется повторять довольно большие одинаковые куски текста. Помимо того, что это утомительно, очень легко допустить ошибку. Если по каким-то причинам потребуется изменить объявление класса, придется изменять все файлы, в которых он используется. Хотя возможно, что изменение никак не затрагивает интерфейс класса. Например, добавление нового внутреннего атрибута непосредственно не влияет на использование внешних методов и атрибутов этого класса.
Использование включаемых файлов
В такой же файл заголовков можно поместить прототипы функций и включать его в другие файлы, там, где функции используются.
Таким образом, текст программы на языке Си++ помещается в файлы двух типов – файлы заголовков и файлы программ. В большинстве случаев имеет смысл каждый класс помещать в отдельный файл, вернее, два файла – файл заголовков для объявления класса и файл программ для определения класса. Имя файла обычно состоит из имени класса. Для файла заголовков к нему добавляется окончание " .h " (иногда, особенно в системе Unix, " .hh " или " .H "). Имя файла программы – опять-таки имя класса с окончанием " .cpp " (иногда " .cc " или " .C ").
Объединять несколько классов в один файл стоит лишь в том случае, если они очень тесно связаны и один без другого не используется.
Давайте посмотрим, что произойдет, если в какой-либо .cpp -файл будет дважды включен файл Book.h :
Еще одно замечание по составлению заголовков. Включайте в заголовок как можно меньше других заголовков. Например, в заголовок Book.h необходимо включить заголовки Item.h и String.h , поскольку класс Book использует их. Однако если используется лишь имя класса без упоминания его содержимого, можно обойтись и объявлением этого имени:
Объявление класса Item требуется знать целиком, для того, чтобы обработать объявление класса Book , т.е. компилятору надо знать все методы и атрибуты Item , чтобы включить их в класс Book . Объявление класса String также необходимо знать целиком, по крайней мере, для того, чтобы правильно вычислить размер экземпляра класса Book . Что же касается класса Annotation , то ни размер его объектов, ни его методы не важны для определения содержимого объекта класса Book . Единственное, что надо знать, это то, что Annotation есть имя некоего класса, который будет определен в другом месте.
Общее правило таково, что если объявление класса использует указатель или ссылку на другой класс и не задействует никаких методов или атрибутов этого класса, достаточно объявления имени класса. Разумеется, полное объявление класса Annotation понадобится в определении метода CreateAnnotation .
Компилятор поставляется с набором файлов заголовков, которые описывают все стандартные функции и классы. При включении стандартных файлов обычно используют немного другой синтаксис:
определяет макроимя. Везде, где в исходном файле встречается это имя, оно будет заменено его определением. Например, текст:
после препроцессора будет заменен на
По умолчанию имя определяется как пустая строка, т.е. после директивы
макроимя XYZ считается определенным со значением – пустой строкой.
определяет макрос – текстовую подстановку с аргументами
Текст max(5, a) будет заменен на
В большинстве случаев использование макросов (как с аргументами, так и без) в языке Си++ является признаком непродуманного дизайна. В языке Си макросы были действительно важны, и без них было сложно обойтись. В Си++ при наличии констант и шаблонов макросы не нужны. Макросы осуществляют текстовую подстановку, поэтому они в принципе не могут осуществлять никакого контроля использования типов. В отличие от них в шаблонах контроль типов полностью сохранен. Кроме того, возможности текстовой подстановки существенно меньше, чем возможности генерации шаблонов.
У препроцессора есть несколько макроимен, которые он определяет сам, их называют предопределенными именами. У разных компиляторов набор этих имен различен, но два определены всегда: __FILE__ и __LINE__ . Значением макроимени __FILE__ является имя текущего исходного файла, заключенное в кавычки. Значением __LINE__ – номер текущей строки в файле. Эти макроимена часто используют для печати отладочной информации.
Условная компиляция
Исходный файл можно компилировать не целиком, а частями, используя директивы условной компиляции:
Дополнительные директивы препроцессора
Ассемблирование и компоновка программы. Получение COM-файлов
15 декабря 2020 mob25
На этом шаге мы рассмотрим порядок получения исполняемых файлов.
Рассмотрим основные этапы перевода программы из ASCII-кода в машинный код.
Текст программы на Ассемблере набирается в любом текстовом редакторе и сохраняется в
файле с расширением ASM. Перевод этого файла в EXE-программу происходит в
два этапа:
- перевод текста программы в машинные коды (ассемблирование);
- сборка готовой программы из отдельных частей и установка адресов ссылок
(компоновка, линковка).
Для ассемблирования используется программа MASM.EXE. При выполнении этой программы
запрашиваются имена четырех файлов:
Если в результате ассемблирования не обнаружено ошибок, то можно переходить к компоновке объектного
модуля. Для ее проведения используется программа LINK.EXE. Она запрашивает имена четырех
файлов:
Если процесс линковки произошел без ошибок, то получится файл с расширением EXE.
Таким образом, на диске будут находиться два файла с одинаковыми именами, но различными расширениями.
В качестве примера получим COM-файл из приведенной на предыдущем шаге программы.
В результате на диске получим файл PR25_1.OBJ.
Поэтому нужно перевести полученный EXE-файл в соответствующий COM-файл (понятно,
что следующий пункт не выполняется для создаваемых EXE-файлов).
Формат использования этой программы следующий (приводится содержимое командной строки):
Здесь 6.22 - номер версии DOS.
Отметим также, что в последних версиях операционной системы Windows в
папке Windows/System32 находится программа EXE2BIN.EXE. В этом
случае можно воспользоваться ею и не обновлять таблицу версий.
В программе из предыдущего шага на экран выводится
число, состоящее из одной цифры. А как вывести на экран многозначное число? Ответ на
этот вопрос мы дадим после рассмотрения других способов передачи управления (шаг
40: "Процедуры ввода и вывода многозначных чисел").
На следующем шаге мы начнем рассматривать команды условного перехода.
Программа – это, прежде всего, текст на языке Си++. С помощью компилятора текст преобразуется в исполняемый файл – форму, позволяющую компьютеру выполнять программу.
На третьем этапе компиляции к объектному файлу подсоединяются все функции на которые он ссылается. Функции тоже должны быть скомпилированы, т.е. переведены на машинный язык в форму объектных файлов . Этот процесс называется компоновкой , и как раз его результат и есть исполняемый файл .
Системные функции и стандартные функции языка Си++ заранее откомпилированы и хранятся в виде библиотек . Библиотека – это некий архив объектных модулей, с которым удобно компоновать программу.
Основная цель многоэтапной компиляции программ – возможность компоновать программу из многих файлов . Каждый файл представляет собой законченный фрагмент программы, который может ссылаться на функции, переменные или классы, определенные в других файлах. Компоновка объединяет фрагменты в одну "самодостаточную" программу, которая содержит все необходимое для выполнения.
Проблема использования общих функций и имен
В языке Си++ существует строгое правило, в соответствии с которым прежде чем использовать в программе имя или идентификатор , его необходимо определить. Рассмотрим для начала функции. Для того чтобы имя функции стало известно программе, его нужно либо объявить, либо определить.
Объявление функции состоит лишь из ее прототипа, т.е. имени, типа результата и списка аргументов. Объявление функции задает ее формат, но не определяет, как она выполняется. Примеры объявлений функций:
Определение функции – это определение того, как функция выполняется. Оно включает в себя тело функции, программу ее выполнения.
Определение функции играет роль объявления ее имени, т.е. если в начале файла определена функция fact , в последующем тексте функций и классов ею можно пользоваться. Однако если в программе функция fact используется в нескольких файлах, такое построение программы уже не подходит. В программе должно быть только одно Определение функции .
Удобно было бы поместить Определение функции в отдельный файл , а в других файлах в начале помещать лишь объявление, прототип функции .
Компоновщик объединит оба файла в одну программу.
Аналогичная ситуация существует и для классов. Любой класс в языке Си++ состоит из двух частей: объявления и определения. В объявлении класса говорится, каков интерфейс класса, какие методы и атрибуты составляют объекты этого класса. Объявление класса состоит из ключевого слова class , за которым следует имя класса , список наследования и затем в фигурных скобках - методы и атрибуты класса. Заканчивается объявление класса точкой с запятой.
Определение класса – это определение всех его методов.
Определение класса должно быть только одно, и если класс используется во многих файлах, его удобно поместить в отдельный файл . В остальных файлах для того, чтобы использовать класс Book , например определить переменную класса Book , в начале файла необходимо поместить объявление класса.
Таким образом, в начале каждого файла будут сосредоточены прототипы всех используемых функций и объявления всех применяемых классов.
Программа работать будет, однако писать ее не очень удобно.
В начале каждого файла нам придется повторять довольно большие одинаковые куски текста. Помимо того, что это утомительно, очень легко допустить ошибку. Если по каким-то причинам потребуется изменить объявление класса, придется изменять все файлы, в которых он используется. Хотя возможно, что изменение никак не затрагивает интерфейс класса. Например, добавление нового внутреннего атрибута непосредственно не влияет на использование внешних методов и атрибутов этого класса.
Все языки программирования делятся на два типа — интерпретируемые и компилируемые.
Интерпретаторы
Программируя на интерпретируемом языке, мы пишем программу не для выполнения в процессоре, а для выполнения программой-интерпретатором. Ее также называют виртуальной машиной.
Как правило, программа преобразуется в некоторый промежуточный код, то есть набор инструкций, понятный виртуальной машине.
При интерпретации выполнение кода происходит последовательно строка за строкой (от инструкции до инструкции). Операционная система взаимодействует с интерпретатором, а не исходным кодом.
Скомпилированные программы работают быстрее, но при этом очень много времени тратится на компиляция исходного кода.
Программы же, рассчитанные на интерпретаторы, могут выполняться в любой системе, где таковой интерпретатор присутствует. Типичный пример — код JavaScript. Интерпретатором его выступает любой современный браузер. Вы можете однократно написать код на JavaScript, включив его в html-файл, и он будет одинаково выполняться в любой среде, где есть браузер. Не важно, будет ли это Safari в Mac OS, или же Internet Explorer в Windows.
Компиляторы
Компилятор — это программа, превращающая исходный текст, написанный на языке программирования, в машинные инструкции.
По мере преобразования текста программы в машинный код, компилятор может обнаруживать ошибки (синтаксиса языка, например). Поэтому все проблемы забытых точек с запятыми, забытых скобок, ошибок в названиях функций и переменных в данном случае решаются на этапе компиляции.
При компиляции весь исходный программный код (тот, который пишет программист) сразу переводится в машинный. Создается так называемый отдельный исполняемый файл, который никак не связан с исходным кодом. Выполнение исполняемого файла обеспечивается операционной системой. То есть образуется, например,.EXE файл.
Примеры компилируемых языков: C, C++, Pascal, Delphi.
Препроцессинг
Эту операцию осуществляет текстовый препроцессор.
Исходный текст частично обрабатывается — производятся:
- Замена комментариев пустыми строками
- Подключение модулей и т. д. и т. п.
Компиляция
Результатом компиляции является объектный код.
Объектный код — это программа на языке машинных кодов с частичным сохранением символьной информации, необходимой в процессе сборки.
Компоновка
Компоновка также может носить следующие названия: связывание, сборка или линковка.
Это последний этап процесса получения исполняемого файла, состоящий из связывания воедино всех объектных файлов проекта.
EXE файл.
Заходим в Сервис -> Настройки -> Опции компиляции. Поверяем, стоит ли галочка напротив 2 пункта. Если стоит, то убираем ее.
Теперь откройте свою программу и запустите ее.
Откройте директорию, в которой у вас лежит исходный код программы.
Кликаем по приложению. Как вы видите, после ввода данных, окошко сразу закрывается. Для того чтобы окно не закрывалось сразу, следует дописать две строчки кода, а именно: uses crt (перед разделом описания переменных) и readkey (в конце кода, перед оператором end).
Подключаем внешнюю библиотеку crt и используем встроенную в нее функцию readkey.
Теперь окно закроется по нажатию любой клавиши.
Среда разработки включает в себя:
- текстовый редактор;
- компилятор;
- средства автоматизации сборки;
- отладчик.
На сегодня все! Задавайте любые вопросы в комментариях к этой статье. Не забывайте кликать по кнопочкам и делится ссылками на наш сайт со своими друзьями. А для того, чтобы не пропустить выход очередной статьи, рекомендую вам подписаться на рассылку новостей от нашего сайта. Одна из них находится в самом верху справа, другая — в футере сайта.
Читайте также: