Условная компиляция
ifdef и макросы
«Условная компиляция» — бесплатный урок C Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
Препроцессор
До того как компилятор увидит Ваш код, запускается препроцессор. Он обрабатывает каждую строку, начинающуюся с #: подключения, макросы и условные конструкции.
Условная компиляция позволяет включать или исключать блоки кода на основе условий, вычисляемых на этом этапе, и получать разные сборки из одного исходного кода.
Определение макросов
#define создаёт макрос. Без значения это просто флаг, наличие которого можно проверить позже.
Макросы, похожие на объекты, заменяют имя текстом; флаги лишь отмечают, что нечто установлено.
#define MAX_USERS 100 /* value macro */
#define DEBUG /* flag macro */ifdef и ifndef
#ifdef NAME оставляет блок только в том случае, если NAME определён. #ifndef оставляет его только в том случае, если NAME не определён.
Здесь отладочная печать существует только в отладочных сборках. Если DEBUG не определён, компилятор вообще не увидит эту строку.
#include <stdio.h>
#define DEBUG
int main(void) {
#ifdef DEBUG
printf("debug: starting\n");
#endif
printf("running\n");
return 0;
}if, elif, else
#if вычисляет константное целочисленное выражение. Объединяйте его с #elif и #else для многостороннего выбора.
Так код выбирается на основе макроса с номером версии.
#include <stdio.h>
#define VERSION 2
int main(void) {
#if VERSION >= 2
printf("new feature on\n");
#else
printf("legacy mode\n");
#endif
return 0;
}Оператор defined
Внутри #if можно проверить, определено ли имя, с помощью defined(NAME), а также объединить проверки операторами && и ||.
Это гибче, чем #ifdef, который может проверять только одно имя.
#if defined(LINUX) && !defined(EMBEDDED)
/* desktop Linux code */
#endifОпределение во время компиляции
Необязательно жёстко задавать макросы в исходном коде. Флаг -D определяет их в командной строке.
Так системы сборки переключают возможности без изменения исходного кода. -DDEBUG эквивалентен #define DEBUG в начале каждого файла.
gcc -DDEBUG -DVERSION=3 -o app app.cОпределение платформы
Компиляторы заранее определяют макросы, описывающие целевую платформу. Используйте их для написания переносимого кода.
_WIN32— Windows (32- или 64-разрядная)__linux__— Linux__APPLE__— macOS / iOS
Используйте эти условия, чтобы вызывать правильный программный интерфейс платформы.
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endifЗащита от повторного подключения заголовка
Классическое применение условных конструкций — защита от повторного подключения, которая не позволяет обработать заголовок дважды.
При первом подключении определяется макрос защиты; последующие подключения пропускают тело, поскольку макрос уже определён.
#ifndef UTILS_H
#define UTILS_H
int add(int a, int b);
#endif /* UTILS_H */Закомментирование кода
#if 0 ... #endif надёжно отключает блок, даже если он уже содержит комментарии.
В отличие от /* */, эта конструкция безопасно вкладывается сама в себя, поэтому это стандартный способ временно исключить код во время отладки.
#if 0
legacy_function(); /* disabled for now */
/* with internal comments too */
#endifПроверка результата препроцессора
Чтобы точно увидеть, что будет компилировать компилятор, запустите только препроцессор с параметром -E.
Он раскроет все подключения, макросы и условные конструкции, что особенно полезно, когда макрос работает неправильно.
gcc -E app.c | lessПереключатели возможностей на практике
Распространённый подход — один заголовок конфигурации, который включает или отключает возможности для всего проекта.
Измените один #define, и каждый защищённый блок во всех файлах отреагирует на это. Так дополнительные возможности остаются чётко отделены от основного кода.
#include <stdio.h>
#define FEATURE_LOGGING 1
int main(void) {
#if FEATURE_LOGGING
printf("logging enabled\n");
#endif
printf("app ready\n");
return 0;
}Быстрая проверка
Предскажите поведение определения из командной строки.
Итоги
Теперь Вы управляете условной компиляцией:
#ifdef/#ifndefпроверяют, определён ли макрос#if/#elif/#elseвычисляют константные выражения с помощьюdefined()-DNAMEопределяет макросы из командной строки для переключения возможностей- Предопределённые макросы платформы обеспечивают переносимость кода, а защита заголовков предотвращает повторное подключение
Далее: организация кода в нескольких файлах.
Часто задаваемые вопросы
Урок «Условная компиляция» бесплатный?
Да — полный текст урока «Условная компиляция» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «Условная компиляция»?
ifdef и макросы Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Условная компиляция»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Условная компиляция
- Многофайловые проекты
- Makefile
- Статические и разделяемые библиотеки