Препроцессор - это отдельный этап обработки исходного кода перед его компиляцией, который выполняет текстовые преобразования согласно специальным директивам.
Подключение заголовочных файлов
#include <iostream> // Стандартная библиотека
#include "myheader.h" // Пользовательский заголовок
Макроподстановки
#define PI 3.14159
#define SQUARE(x) ((x)*(x))
Условная компиляция
#ifdef DEBUG
#define LOG(msg) std::cout << msg << std::endl
#else
#define LOG(msg)
#endif
Другие директивы
#pragma once // Защита от множественного включения
#error "Не поддерживаемая конфигурация"
#warning "Возможная проблема"
Исходный код:
#include <iostream>
#define MESSAGE "Hello World"
int main() {
std::cout << MESSAGE << std::endl;
return 0;
}
После препроцессинга:
// Содержимое iostream (сотни строк)
int main() {
std::cout << "Hello World" << std::endl;
return 0;
}
Только текстовая замена:
Файлы включения:
Предопределенные макросы:
__LINE__ // Текущая строка
__FILE__ // Имя файла
__DATE__ // Дата компиляции
__cplusplus // Версия C++
Макросы vs inline-функции:
// Проблемный макрос
#define MAX(a,b) a > b ? a : b
MAX(i++, j++) // Двойное инкрементирование!
// Лучше использовать:
inline int max(int a, int b) { return a > b ? a : b; }
Загрязнение пространства имен:
Отладка:
Используйте #pragma once вместо стражей включения:
#pragma once // Современный способ
// Устаревший способ:
#ifndef HEADER_H
#define HEADER_H
/* код */
#endif
Избегайте сложных макросов:
Проверяйте результат препроцессинга:
g++ -E file.cpp -o file.ii
clang -E file.cpp -o file.ii
Модули C++20:
Constexpr:
Атрибуты:
Резюмируем: препроцессор - мощный, но примитивный инструмент текстовой обработки, критически важный для работы C/C++ программ. Хотя современные возможности C++ предлагают более безопасные альтернативы многим функциям препроцессора, он остается неотъемлемой частью языка и инструментария разработчика.