Skip to content

Компилятор

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

Компиляторов языка C существует огромное множество, но я использую GCC. GCC есть под каждую распространенную архитектуру процессора(даже для процессоров Baikal) и ОС. В большинстве UNIX-подобных систем компилятор уже установлен. Если у вас другая ОС, то скачать компилятор можно по ссылке.

Пример простого кода, выводящего в терминал: "Hello, World!":

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    puts("Hello, World!");
    return EXIT_SUCCESS;
}

Перед тем как запустить программу, необходимо её скомпилировать.

cc назмание_файла.c -o program # Сборка программы
./program # Запуск программы

ВАЖНО: команды выполяются в коммандном интерпритаторе BASH.

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

  1. Препроцессинг

  2. Транслирование кода в ассемблер

  3. Ассемблирование

  4. Линковка

Препроцессинг

На данном этапе происходит работа с препроцессорными директивами.

header-файлы файлы stdio.h и stdlib.h, которые предоставляют своеобраный API. #include препроцессорная директива(есть в коде выше) подключающая header-файлы.

После препроцессинга код имеет приблизительно следующий вид:

/*
 *Код из stdio.h 
 */
extern void puts(const char *);
/*
 *Код из stdlib.h 
 */
#define EXIT_SUCCESS 0

int
main(int argc, char *argv[])
{
    puts("Hello, World!");
    return EXIT_SUCCESS;
}

#define тоже является препроцессорной директивой. Она определяет/переопределяет синтаксические выражения, в данном случае EXIT_SUCCESS определено как 0.

Поэтому код преобразуется приблизительно в следующий вид:

/*
 *Код из stdio.h 
 */
extern void puts(const char *);
/*
 *Код из stdlib.h 
 */

int
main(int argc, char *argv[])
{
    puts("Hello, World!");
    return 0; // EXIT_SUCCESS заменился на 0
}

Чтобы посмотреть что получится после этапа препроцессинга:

cc -E название_файла.c -o program.ii
В файле program.ii будет лежать код прошедший этап препроцессинга.

ВАЖНО: Для успешного повторения команд понадобятся сгенерированные файлы program.ii, program.s, program.o. Последние два генерируются в следующиъ пунктах.

Транслирование кода в ассемблер

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

cc -S program.ii -o program.s
В файле program.s будет лежать код на языке ассемблера.

Ассемблирование

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

as program.s -o program.o
В файле program.o будет лежать машинный код.

Линковка

Линковка - процесс "связывания" всех объектных файлов в один исполняемый файл.

Чтобы посмотреть что получится после этапа линковки:

cc program.o -o program

Чтобы запустить программу:

./program

Вывод

В данном курсе была рассмотрена тема компиляции, что полезно каждому начинающему программисту