- Процесс компиляции программ на C++
- Цель данной статьи:
- Состав компилятора g++
- Зачем нужно компилировать исходные файлы?
- Этапы компиляции:
- 1) Препроцессинг
- 2) Компиляция
- 3) Ассемблирование
- 4) Компоновка
- 5) Загрузка
- Заключение
- Исходные файлы
- Интерпретаторы
- Компиляторы
- Ход работы компилятора.
- Препроцессинг
- Компиляция
- Компоновка
- EXE файл.
- Русские Блоги
- От исходного кода до исполняемого файла
- Компьютер может запускать только локальный код
- Содержание нативного кода
- Компилятор отвечает за преобразование исходного кода
- Вы не можете получить исполняемые файлы, просто скомпилировав
- Интеллектуальная рекомендация
- Два типа 5,6 классов и структур [SWIFT оригинальный учебник]
- Установите Nginx, Mysql, PHP, Redis на Mac
- Hangdian 2010 Количество нарциссов
- Конфигурация спящего аннотации ManyToMany
- Eclipse пропускает проверку в папке
- Русские Блоги
- 1. Пример программы
- 2. Предварительная обработка
- 3. Компилировать
- 4. Компиляция
- 5. Ссылка
Процесс компиляции программ на C++
Цель данной статьи:
В данной статье я хочу рассказать о том, как происходит компиляция программ, написанных на языке C++, и описать каждый этап компиляции. Я не преследую цель рассказать обо всем подробно в деталях, а только дать общее видение. Также данная статья — это необходимое введение перед следующей статьей про статические и динамические библиотеки, так как процесс компиляции крайне важен для понимания перед дальнейшим повествованием о библиотеках.
Все действия будут производиться на Ubuntu версии 16.04.
Используя компилятор g++ версии:
Состав компилятора g++
Мы не будем вызывать данные компоненты напрямую, так как для того, чтобы работать с C++ кодом, требуются дополнительные библиотеки, позволив все необходимые подгрузки делать основному компоненту компилятора — g++.
Зачем нужно компилировать исходные файлы?
Исходный C++ файл — это всего лишь код, но его невозможно запустить как программу или использовать как библиотеку. Поэтому каждый исходный файл требуется скомпилировать в исполняемый файл, динамическую или статическую библиотеки (данные библиотеки будут рассмотрены в следующей статье).
Этапы компиляции:
driver.cpp:
1) Препроцессинг
Самая первая стадия компиляции программы.
Препроцессор — это макро процессор, который преобразовывает вашу программу для дальнейшего компилирования. На данной стадии происходит происходит работа с препроцессорными директивами. Например, препроцессор добавляет хэдеры в код (#include), убирает комментирования, заменяет макросы (#define) их значениями, выбирает нужные куски кода в соответствии с условиями #if, #ifdef и #ifndef.
Хэдеры, включенные в программу с помощью директивы #include, рекурсивно проходят стадию препроцессинга и включаются в выпускаемый файл. Однако, каждый хэдер может быть открыт во время препроцессинга несколько раз, поэтому, обычно, используются специальные препроцессорные директивы, предохраняющие от циклической зависимости.
Получим препроцессированный код в выходной файл driver.ii (прошедшие через стадию препроцессинга C++ файлы имеют расширение .ii), используя флаг -E, который сообщает компилятору, что компилировать (об этом далее) файл не нужно, а только провести его препроцессинг:
Взглянув на тело функции main в новом сгенерированном файле, можно заметить, что макрос RETURN был заменен:
В новом сгенерированном файле также можно увидеть огромное количество новых строк, это различные библиотеки и хэдер iostream.
2) Компиляция
На данном шаге g++ выполняет свою главную задачу — компилирует, то есть преобразует полученный на прошлом шаге код без директив в ассемблерный код. Это промежуточный шаг между высокоуровневым языком и машинным (бинарным) кодом.
Ассемблерный код — это доступное для понимания человеком представление машинного кода.
Используя флаг -S, который сообщает компилятору остановиться после стадии компиляции, получим ассемблерный код в выходном файле driver.s:
Мы можем все также посмотреть и прочесть полученный результат. Но для того, чтобы машина поняла наш код, требуется преобразовать его в машинный код, который мы и получим на следующем шаге.
3) Ассемблирование
Так как x86 процессоры исполняют команды на бинарном коде, необходимо перевести ассемблерный код в машинный с помощью ассемблера.
Ассемблер преобразовывает ассемблерный код в машинный код, сохраняя его в объектном файле.
Объектный файл — это созданный ассемблером промежуточный файл, хранящий кусок машинного кода. Этот кусок машинного кода, который еще не был связан вместе с другими кусками машинного кода в конечную выполняемую программу, называется объектным кодом.
Далее возможно сохранение данного объектного кода в статические библиотеки для того, чтобы не компилировать данный код снова.
Получим машинный код с помощью ассемблера (as) в выходной объектный файл driver.o:
Но на данном шаге еще ничего не закончено, ведь объектных файлов может быть много и нужно их всех соединить в единый исполняемый файл с помощью компоновщика (линкера). Поэтому мы переходим к следующей стадии.
4) Компоновка
Компоновщик (линкер) связывает все объектные файлы и статические библиотеки в единый исполняемый файл, который мы и сможем запустить в дальнейшем. Для того, чтобы понять как происходит связка, следует рассказать о таблице символов.
Таблица символов — это структура данных, создаваемая самим компилятором и хранящаяся в самих объектных файлах. Таблица символов хранит имена переменных, функций, классов, объектов и т.д., где каждому идентификатору (символу) соотносится его тип, область видимости. Также таблица символов хранит адреса ссылок на данные и процедуры в других объектных файлах.
Именно с помощью таблицы символов и хранящихся в них ссылок линкер будет способен в дальнейшем построить связи между данными среди множества других объектных файлов и создать единый исполняемый файл из них.
Получим исполняемый файл driver:
5) Загрузка
Последний этап, который предстоит пройти нашей программе — вызвать загрузчик для загрузки нашей программы в память. На данной стадии также возможна подгрузка динамических библиотек.
Запустим нашу программу:
Заключение
В данной статье были рассмотрены основы процесса компиляции, понимание которых будет довольно полезно каждому начинающему программисту. В скором времени будет опубликована вторая статья про статические и динамические библиотеки.
Исходные файлы
Исходные файлы
Текст программы на языке Си может быть разделен на несколько исходных файлов. Исходный файл представляет собой текстовый файл, который содержит либо всю программу, либо ее часть. При компиляции исходной программы каждый из составляющих ее исходных файлов должен быть скомпилирован отдельно, а затем связан с другими файлами компоновщиком. Отдельные исходные файлы можно объединять в один исходный файл, компилируемый как единое целое, посредством директивы препроцессора #include.
Исходный файл может содержать любую целостную комбинацию директив, указаний компилятору, объявлений и определений. Под целостностью подразумевается, что такие объекты, как определения функций, структуры данных либо набор связанных между собой директив условной компиляции, должны целиком располагаться в одном файле, т. е. не могут начинаться в одном файле, а продолжаться в другом.
Исходный файл не обязательно должен содержать выполняемые операторы. Иногда удобно размещать определения переменных в одном файле, а в других файлах использовать эти переменные путем их объявления. В этом случае определения переменных становятся легко доступными для поиска и модификации. Из тех же соображений именованные константы и макроопределения обычно собирают в отдельные файлы и включают их посредством директивы препроцессора #include в те исходные файлы, в которых они требуются.
Указания компилятору обычно действуют только для отдельных участков исходного файла. Специфические действия компилятора, задаваемые указаниями, определяются конкретной реализацией компилятора языка Си.
В нижеследующем примере исходная программа состоит из двух исходных файлов. Функции main и max представлены в отдельных файлах. Функция main использует функцию max в процессе своего выполнения.
/* исходный файл 1 — функция main */
extern int max (int, int); /* объявление функции */
Здравствуйте, дорогие читатели! Сегодня мы с вами немного окунемся в теорию. Наверняка, вы все когда-то хотели отправить свою супер-пупер программу другу. Но как это сделать? Не заставлять же его устанавливать PascalABC.NET! О том, как это сделать, мы сегодня и поговорим.
Все языки программирования делятся на два типа — интерпретируемые и компилируемые.
Интерпретаторы
Программируя на интерпретируемом языке, мы пишем программу не для выполнения в процессоре, а для выполнения программой-интерпретатором. Ее также называют виртуальной машиной.
Как правило, программа преобразуется в некоторый промежуточный код, то есть набор инструкций, понятный виртуальной машине.
При интерпретации выполнение кода происходит последовательно строка за строкой (от инструкции до инструкции). Операционная система взаимодействует с интерпретатором, а не исходным кодом.
Примеры интерпретируемых языков: PHP, JavaScript, C#, Python.
Скомпилированные программы работают быстрее, но при этом очень много времени тратится на компиляция исходного кода.
Программы же, рассчитанные на интерпретаторы, могут выполняться в любой системе, где таковой интерпретатор присутствует. Типичный пример — код JavaScript. Интерпретатором его выступает любой современный браузер. Вы можете однократно написать код на JavaScript, включив его в html-файл, и он будет одинаково выполняться в любой среде, где есть браузер. Не важно, будет ли это Safari в Mac OS, или же Internet Explorer в Windows.
Компиляторы
Компилятор — это программа, превращающая исходный текст, написанный на языке программирования, в машинные инструкции.
По мере преобразования текста программы в машинный код, компилятор может обнаруживать ошибки (синтаксиса языка, например). Поэтому все проблемы забытых точек с запятыми, забытых скобок, ошибок в названиях функций и переменных в данном случае решаются на этапе компиляции.
При компиляции весь исходный программный код (тот, который пишет программист) сразу переводится в машинный. Создается так называемый отдельный исполняемый файл, который никак не связан с исходным кодом. Выполнение исполняемого файла обеспечивается операционной системой. То есть образуется, например,.EXE файл.
Примеры компилируемых языков: C, C++, Pascal, Delphi.
Ход работы компилятора.
Препроцессинг
Эту операцию осуществляет текстовый препроцессор.
Исходный текст частично обрабатывается — производятся:
Компиляция
Результатом компиляции является объектный код.
Объектный код — это программа на языке машинных кодов с частичным сохранением символьной информации, необходимой в процессе сборки.
Компоновка
Компоновка также может носить следующие названия: связывание, сборка или линковка.
Это последний этап процесса получения исполняемого файла, состоящий из связывания воедино всех объектных файлов проекта.
EXE файл.
После компоновки у вас образуется.EXE файл вашей программы. Вы можете кинуть ее другу, и она откроется у него прямо в командной строке, как в старом добром DOS. Давайте попробуем создать.EXE файл. Все действия будут приводится в PascalABC.NET.
Теперь откройте свою программу и запустите ее.
Откройте директорию, в которой у вас лежит исходный код программы.
Кликаем по приложению. Как вы видите, после ввода данных, окошко сразу закрывается. Для того чтобы окно не закрывалось сразу, следует дописать две строчки кода, а именно: uses crt (перед разделом описания переменных) и readkey (в конце кода, перед оператором end).
Подключаем внешнюю библиотеку crt и используем встроенную в нее функцию readkey.
Теперь окно закроется по нажатию любой клавиши.
На заметку:
— это интегрированная среда разработки.Среда разработки включает в себя:
На сегодня все! Задавайте любые вопросы в комментариях к этой статье. Не забывайте кликать по кнопочкам и делится ссылками на наш сайт со своими друзьями. А для того, чтобы не пропустить выход очередной статьи, рекомендую вам подписаться на рассылку новостей от нашего сайта. Одна из них находится в самом верху справа, другая — в футере сайта.
Русские Блоги
От исходного кода до исполняемого файла
Компьютер может запускать только локальный код
Программа, написанная на определенном языке программирования, называется исходным кодом, а файл, в котором сохраняется исходный код, называется исходным файлом. Исходный код нельзя запустить напрямую, потому что ЦП может напрямую анализировать и запускать программы, которые не являются исходным кодом, а являются собственным кодом. ЦП, как мозг компьютера, может интерпретировать только содержимое программы, преобразованной в локальный код.
Содержание нативного кода
Компилятор отвечает за преобразование исходного кода
Программа, которая может преобразовывать исходный код, написанный на языке программирования высокого уровня, таком как язык C, в локальный код, называется компилятором. Каждый язык программирования, который пишет исходный код, требует своего собственного выделенного компилятора.
Компилятор сначала считывает содержимое исходного кода, а затем преобразует исходный код в локальный код. Кажется, есть таблица соответствия между исходным кодом и собственным кодом в компиляторе. Но на самом деле генерировать нативный код только по таблице соответствия невозможно. Считанный исходный код должен пройти грамматический анализ, синтаксический анализ, семантический анализ и т. Д. Для генерации собственного кода.
В зависимости от типа ЦП различается и собственный код. Таким образом, компилятор связан не только с типом языка программирования, но и с типом процессора.
Вы не можете получить исполняемые файлы, просто скомпилировав
Компилятор генерирует машинный код после преобразования исходного кода, но собственный код не может быть запущен напрямую. Чтобы получить исполняемые файлы, которые можно запустить, после компиляции требуется обработка «ссылок». Процесс объединения нескольких целевых файлов для создания исполняемого файла является компоновщиком, а программа, запускающая ссылку, называется компоновщиком.
Интеллектуальная рекомендация
Два типа 5,6 классов и структур [SWIFT оригинальный учебник]
Оригинал:http://coolketang.com/staticCoding/5a9925ac17d0090035986868.html 1. В настоящем разделе приводится сравнение характеристик категории и структуры класса, так что вы можете более четко понимать.
Установите Nginx, Mysql, PHP, Redis на Mac
информация об оборудовании: macOS Sierra (версия 10.12.1) Процессор Intel Core i5 с тактовой частотой 2,6 ГГц Оперативная память 8 ГБ 1600 МГц DDR3 Команда для установки инструмента командной строки x.
Hangdian 2010 Количество нарциссов
Конфигурация спящего аннотации ManyToMany
Отношение прав доступа пользователя Три таблицы базы данных участвуют SYS_USER,SYS_USER_ROLE,SYS_ROLE Класс пользователя Класс разрешений Это включает аннотации JPA и аннотации Hibernate, которые в ос.
Eclipse пропускает проверку в папке
первый шаг: выберите проект, щелкните правой кнопкой мыши, чтобы найти свойства Шаг 2: Шаг 3. Выберите исключенный, выберите «Изменить», добавьте папку или тип файла проверки, которую необхо.
Русские Блоги
Автор: Yeh
Источник:http://lxWei.github.io/posts/262.html
Отказ от ответственности: Пожалуйста, укажите автора и источник перепечатки.
Жизненный цикл программы начинается с программы на языке высокого уровня C. Эта форма может быть понятна людям, но не может быть понята машинами. Чтобы запустить эту программу в системе, исходная программа должна быть преобразована в ряд машинных языков низкого уровня другими программами. Инструкции, которые затем упаковываются в виде исполняемых объектных программ и хранятся в виде двоичных файлов на диске.
В системе Linux следующие инструкции могут быть использованы для завершения преобразования исходной программы в целевую программу:
Драйвер компилятора gcc считывает исходные файлы hello.c и main.c и производит предварительную обработку, компиляцию, сборку и ссылки (с использованием препроцессора, компилятора, ассемблера и компоновщика соответственно. Эти четыре программы составляют систему компиляции ) Четыре шага, чтобы перевести его в исполняемую целевую программу привет. Как показано ниже:
Запустите следующую команду:
Как показано на рисунке ниже, соответствует четырем этапам на рисунке выше:
1. Пример программы
2. Предварительная обработка
Выполните следующую команду, чтобы увидеть изменения программы:
Посмотрите на hello.i, как показано ниже (аналогично main.i):
Как видно из приведенного выше рисунка, предварительная обработка является только расширением исходного файла, и исходная программа на языке C все еще получается.
3. Компилировать
Компилятор (CCL) переводит текстовые файлы hello.i и main.i, обработанные препроцессором, в hello.s и main.s, которые содержат программы на языке ассемблера. Программы на языке ассемблера находятся точно в стандартном текстовом формате. Описывает низкоуровневую инструкцию машинного языка.
Выполните следующую команду для компиляции:
Посмотрите на main.s и hello.s:
4. Компиляция
Выполните следующие инструкции, чтобы получить программы ретаргетинга main.o и hello.o:
Откройте main.o и hello.o в текстовом редакторе и найдите, что файлы искажены, потому что они уже являются двоичными файлами.
5. Ссылка
Компоновщик (LD) объединяет main.o и hello.o и некоторые другие необходимые объектные файлы для создания исполняемого объектного файла.
Получите исполняемую программу привет.