Перейти к содержимому
На этой странице

Препроцессор и макросы

Все темы C++ Developer

Подтемы:

Что такое препроцессор?

Препроцессор в C++ — это инструмент, который выполняет предварительную обработку исходного кода перед его компиляцией. Препроцессор обрабатывает директивы, начинающиеся с символа #, такие как #include для включения файлов, #define для определения макросов, #ifdef и #ifndef для условной компиляции. Препроцессор занимается раскрытием макросов, включением кода и удалением комментариев, тем самым подготавливая код к следующим этапам компиляции.


Как работает препроцессор?

Препроцессор в C++ обрабатывает исходный код до его компиляции. Он выполняет следующие задачи:

  1. Обработка директив: Распознает и выполняет инструкции, начинающиеся с символа #, такие как #include для включения содержимого других файлов, #define для создания макросов, и директивы условной компиляции (#if, #ifdef, #ifndef).

  2. Раскрытие макросов: Заменяет макросы их значениями в коде.

  3. Удаление комментариев: Удаляет комментарии из кода, чтобы они не мешали компиляции.

  4. Вставка кода: Вставляет содержимое файлов, указанных в #include, непосредственно в место включения.

Эти действия выполняются ещё до того, как компилятор начинает анализировать и трансформировать код в машинный язык.


Какие директивы вы знаете?

Основные директивы препроцессора:

  1. #include - включает содержимое одного файла в другой в момент компиляции.

  2. #define - определяет макросы, которые заменяются значениями или блоками кода.

  3. #undef - отменяет определение макроса.

  4. #if , #elif , #else , #endif - используются для условной компиляции кода.

  5. #ifdef - проверяет, определен ли макрос перед компиляцией кода в блоке.

  6. #ifndef - проверяет, не определен ли макрос, и выполняет код в блоке, если это так.

  7. #error - выводит сообщение об ошибке и останавливает компиляцию, если встречается в коде.

  8. #pragma - используется для указания специфических инструкций компилятору, зависящих от платформы или компилятора.


Как работает директива include?

Директива #include в C++ используется для включения содержимого одного файла в другой файл во время компиляции. Она берёт все содержимое указанного файла и вставляет его в место, где стоит директива #include. Это обычно используется для включения заголовочных файлов, которые содержат объявления классов, функций, макросов и других элементов, чтобы они были доступны в нескольких файлах исходного кода.

Существует два способа использования #include:

  1. С угловыми скобками ( #include <filename> ): Используется для включения стандартных библиотечных файлов или файлов, которые не находятся в текущей директории исходного кода. Компилятор ищет эти файлы в стандартных системных директориях.

  2. С двойными кавычками ( #include "filename" ): Используется для включения файлов, которые находятся в той же директории, что и файл исходного кода, или в пути поиска, указанном компилятору. Это предпочтительный способ для пользовательских заголовочных файлов.

Директива #include просто вставляет содержимое файла в точку включения, поэтому она не добавляет какого-либо дополнительного функционала, кроме объединения текста файлов во время компиляции.


Как работает директива define?

Директива #define в C++ используется препроцессором для определения макросов. Макросы — это фрагменты кода, которые могут быть вставлены в другие части программы. Основное применение #define — это создание констант и макросов функций.

Вот как она работает:

  1. Определение константы: #define может использоваться для определения символьных констант, что позволяет заменять идентификаторы на определённые значения во время компиляции. Например:

    #define PI 3.14159

    Здесь, всякий раз, когда PI встречается в коде, препроцессор заменяет его на 3.14159.

  2. Макрос функции: #define также может определять макросы, которые ведут себя подобно функциям, но без накладных расходов на вызов функции. Например:

    #define SQUARE(x) ((x) * (x))

    Этот макрос берет один параметр x и заменяет его использование на выражение (x * x).

#define просто текстовая замена, и она происходит перед компиляцией кода. Это значит, что она не влияет на время выполнения программы и не проводит проверок типов или вычислений до того, как код будет скомпилирован.


Как работают макросы?

Макросы в программировании, особенно в C и C++, работают как инструменты для текстовой замены в исходном коде перед его компиляцией. Макросы определяются с помощью директивы препроцессора #define, и вот как они работают:

  1. Определение макроса: Используя #define, вы определяете макрос, который может быть как простым текстом, так и параметризированной функцией. Например:

    #define PI 3.14159
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
  2. Замена: Во время препроцессинга, каждое вхождение имени макроса в коде заменяется его определением. Препроцессор просто заменяет текст без учета контекста или типов данных.

  3. Компиляция: После замены макросов исходный код компилируется. Замененный текст обрабатывается как обычный код программы.

Макросы полезны для:

  • Создания констант.

  • Реализации небольших функций без накладных расходов вызова функций.

  • Условной компиляции кода.

Макросы могут приводить к повторному вычислению аргументов. Например, MAX(a++, b) может увеличить a больше одного раза. Для вычислений предпочтительны функции и шаблоны, а для констант constexpr; они проверяют типы и соблюдают правила области видимости.

Собеседования: C++

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: C++-разработчик, Разработчик системного ПО. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.