<MyRusakov.ru />

Профессия Web-разработчик

Профессия Web-разработчик

Этот комплект за 8 месяцев превратит Вас в Web-разработчика с нуля. Учиться достаточно 1 час в день.

Начнёте Вы с HTML, CSS и вёрстки сайтов. Потом перейдёте к программированию и JavaScript. Затем изучите PHP, MySQL, SQL, Python. Изучите Web-фреймворки Laravel и Django. Создадите 5 своих сайтов для портфолио.

Комплект содержит:

- 540 видеоуроков

- 110 часов видео

- 1205 заданий для закрепления материала из уроков

- 5 финальных тестов

- 7 сертификатов

- 12 Бонусных курсов

Подробнее
Подписка

Подпишитесь на мой канал на YouTube, где я регулярно публикую новые видео.

YouTube Подписаться

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Какая тема Вас интересует больше?

Препроцессор C++: макросы, #include, #ifdef — практическое руководство с примерами

Препроцессор C++: макросы, #include, #ifdef — практическое руководство с примерами

Препроцессор C++ — это этап до компиляции, который обрабатывает директивы вида #include, #define, #if, #ifdef и другие. Понимание его работы помогает избежать загадочных ошибок линковки, конфликтов имён и странного поведения «магических» макросов, а также грамотно настраивать сборку под разные платформы и режимы (Debug/Release).

#include и защита заголовков

#include буквально копирует содержимое файла на место директивы. Чтобы заголовки не подключались повторно (и не вызывали ошибки множественного определения), используют include guards или #pragma once.

// utils.h
#ifndef UTILS_H_INCLUDED
#define UTILS_H_INCLUDED

int add(int a, int b);

#endif // UTILS_H_INCLUDED

Современная альтернатива — #pragma once (поддерживается большинством компиляторов):

// utils.h
#pragma once
int add(int a, int b);

Косые скобки и кавычки в #include важны: #include <iostream> ищет в системных путях, а #include "utils.h" — сперва рядом с текущим файлом.

Макросы #define: константы и «функции»

Макросы заменяются текстуально. Для констант лучше предпочитать constexpr, но знать макросы полезно.

#define PI 3.141592653589793

constexpr double kPi = 3.141592653589793; // безопаснее и типобезопасно

Функциональные макросы часто таят ловушки из-за побочных эффектов и приоритетов операторов. Минимум — всегда оборачивайте параметры и всё выражение в скобки.

#define SQR(x) ((x) * (x))

int i = 3;
int a = SQR(i);     // OK: 9
int b = SQR(i++);   // ПЛОХО: i инкрементируется дважды!

constexpr int sqr(int x) { return x * x; } // правильная альтернатива
int c = sqr(i++);   // Безопасно: i++ выполнится один раз

Часто макросы используются для логирования: удобно добавлять файл, строку и имя функции с помощью предопределённых идентификаторов.

#include <iostream>

#define LOG(msg) \
  std::cout << __FILE__ << ":" << __LINE__ << " " << __func__ \
            << " | " << (msg) << '\n';

void run() {
  LOG("started");
}

# и ##: строкизация и склейка токенов

Оператор # превращает аргумент макроса в строковый литерал, а ## склеивает токены.

#define STR(x) #x
#define CAT(a, b) a##b

int xy = 42;

static_assert(sizeof(STR(Hello)) > 0, "");
// STR(Hello world) -> "Hello world"
// CAT(x, y) -> идентификатор xy

Эти приёмы полезны при генерации однотипного кода, но не злоупотребляйте ими — читаемость важнее.

Условная компиляция: #if, #ifdef, #ifndef

С помощью условной компиляции легко настраивать код под платформы, компиляторы и режимы сборки.

#if defined(_WIN32)
  const char* OS = "Windows";
#elif defined(__linux__)
  const char* OS = "Linux";
#elif defined(__APPLE__)
  const char* OS = "Apple";
#else
  const char* OS = "Unknown";
#endif

Отладочные макросы удобно включать/выключать через NDEBUG.

#include <iostream>

#ifndef NDEBUG
  #define DBG(expr) do { \
    std::cerr << "DBG: " << #expr << " = " << (expr) << '\n'; \
  } while(0)
#else
  #define DBG(expr) do { } while(0)
#endif

int calc(int x) { return x * 2; }

int main() {
  int v = 21;
  DBG(calc(v));
}

Передача определений из командной строки компилятора:

g++ main.cpp -DNDEBUG -O2 -std=c++20 -o app
clang++ main.cpp -DAPP_VERSION=\"1.2.3\" -o app

В CMake это можно сделать так:

target_compile_definitions(app PRIVATE NDEBUG APP_VERSION=\"1.2.3\")

Частые ошибки и как их избежать

  • Побочные эффекты в макросах: выражения вроде SQR(i++) приведут к двойному инкременту. Используйте constexpr функции.
  • Отсутствие скобок: #define MUL(a,b) a*b сломается для 1+2*3+4. Пишите ((a)*(b)).
  • Многострочные макросы без \ в конце строки — синтаксическая ошибка. Применяйте шаблон do { ... } while(0) для надёжности.
  • Конфликты имён: глобальные макросы загрязняют пространство имён. Используйте префиксы и #undef после использования, если нужно.
  • Windows min/max из windows.h как макросы ломают std::min/std::max. Решение: #define NOMINMAX перед #include <windows.h>.

Лучшие практики

  • Для констант используйте constexpr и enum class; для «функций» — constexpr/inline функции.
  • Всегда ставьте include guards или #pragma once в заголовках.
  • Используйте макросы для: логирования, платформенных различий, генерации однотипного кода (осторожно), фич-флагов сборки.
  • Именуйте макросы SCREAMING_SNAKE_CASE, не переопределяйте имена из стандартной библиотеки.
  • Минимизируйте область видимости макросов: определяйте их ближе к месту использования и по возможности #undef после.

Мини-проверка понимания

  • Сможете ли вы объяснить, почему SQR(i++) опасно?
  • Чем #include <...> отличается от #include "..."?
  • Когда стоит предпочесть constexpr вместо макроса?

Что дальше изучить

Разобравшись с препроцессором C++, вы будете реже сталкиваться с «мистическими» ошибками сборки и напишете чище код. Хотите прокачаться системно и на практике? Загляните в курс Прокачать C++ на практике → «Программирование на C++ с Нуля до Гуру» — пошаговые модули, задания и разборы для уверенного роста от базовых тем до продвинутых приёмов.

Итог: препроцессор — мощный, но требующий дисциплины инструмент. Знайте его сильные стороны (условная компиляция, логирование, генерация кода) и выбирайте современные альтернативы там, где это повышает безопасность и читаемость.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (https://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: https://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: https://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.