Компиляция C++ программы проходит через несколько ключевых этапов:
Рассмотрим каждый этап подробно.
Препроцессор обрабатывает исходный код перед компиляцией:
// Исходный файл example.cpp
#include <iostream>
#define SQUARE(x) ((x)*(x))
int main() {
std::cout << SQUARE(5) << std::endl;
}
После препроцессинга:
// Содержимое iostream и другие включения
// Макрос SQUARE раскрыт
int main() {
std::cout << ((5)*(5)) << std::endl;
}
Как посмотреть результат препроцессинга:
g++ -E example.cpp -o example.ii
Компилятор преобразует препроцессированный код в ассемблер:
Результат - ассемблерный файл (пример для x86):
main:
pushq %rbp
movq %rsp, %rbp
movl $25, %esi
movl $_ZSt4cout, %edi
call _ZNSolsEi
...
Как получить ассемблерный код:
g++ -S example.cpp -o example.s
Ассемблер преобразует ассемблерный код в объектный файл:
Объектный файл содержит:
Формат объектного файла:
Линковщик объединяет объектные файлы в исполняемый:
Типы линковки:
C++ использует декорирование имен для поддержки:
Пример:
void foo(int) → _Z3fooi
void foo(double) → _Z3food
Можно сохранить промежуточные результаты:
.ii
.s
.o
.exe
(Windows)# Препроцессинг
g++ -E main.cpp -o main.ii
# Компиляция в ассемблер
g++ -S main.ii -o main.s
# Ассемблирование
as main.s -o main.o
# Линковка
g++ main.o -o program
# Или одной командой:
g++ main.cpp -o program
Двухфазная компиляция:
Инстанцирование шаблонов:
Полезные флаги GCC/Clang:
-v
: подробный вывод-###
: показать команды без выполнения-save-temps
: сохранить временные файлы-M
: показать зависимости-Wall -Wextra
: дополнительные предупрежденияРезюмируем: компиляция C++ программы - многоэтапный процесс преобразования исходного кода в исполняемый файл, включающий препроцессинг, компиляцию в ассемблер, ассемблирование в объектный код и линковку. Понимание этого процесса важно для эффективной разработки и отладки сложных проектов.