--- title: Preprocessors localeTitle: Препроцессоры --- ## Препроцессоры в C / CPP Как видно из названия, препроцессоры - это программы, которые обрабатывают наш исходный код перед компиляцией. Существует несколько шагов, связанных с написанием программы и выполнением программы на C / C ++. Давайте посмотрим на эти шаги, прежде чем мы начнем узнавать о препроцессорах. ![Img](https://cdn-media-1.freecodecamp.org/imgr/Pb0aTkV.png) Вы можете увидеть промежуточные шаги на приведенной выше диаграмме. Исходный код, написанный программистами, хранится в файле program.c. Затем этот файл обрабатывается препроцессорами, а файл расширенного исходного кода создается с именем program. Этот расширенный файл компилируется компилятором и создается файл объектного кода с именем program.obj. Наконец, компоновщик связывает этот файл объектного кода с объектным кодом библиотечных функций для генерации исполняемого файла program.exe. Препроцессорные программы предоставляют директивы препроцессоров, которые сообщают компилятору предварительно обработать исходный код перед компиляцией. Все эти директивы препроцессора начинаются с символа `#` (хеш). Этот символ ('#') в начале инструкции в программе C / C ++ указывает, что это предпроцессорная директива. Мы можем разместить эти предпроцессорные директивы в любой нашей программе. Примерами некоторых препроцессорных директив являются: `#include` , `#define` , `#ifndef` и т. Д. ### Типы предпроцессорных директив: 1. макрос 2. Включение файлов 3. Условная компиляция 4. Другие директивы ### Макросы: Макросы являются частью кода в программе, которому дано какое-то имя. Всякий раз, когда это имя встречается компилятором, компилятор заменяет это имя фактическим фрагментом кода. Директива `#define` используется для определения макроса. ```cpp #include #define LIMIT 3 int main() { for(int i=0; i < LIMIT; i++) { std::cout<` где file\_name - это имя файла, который будет включен. Скобки `<` и `>` сообщают компилятору искать файл в стандартном каталоге. * \#### Пользовательские файлы: Когда программа становится очень большой, целесообразно разделить ее на более мелкие файлы и включать в случае необходимости. Эти типы файлов являются определяемыми пользователем файлами. Эти файлы могут быть включены как: ... `#include"filename"` ### Условная компиляция: Условные директивы компиляции - это типы директив, которые помогают скомпилировать определенную часть программы или пропустить компиляцию некоторой определенной части программы на основе некоторых условий. Это можно сделать с помощью двух команд предварительной обработки `ifdef` и `endif` . #### Синтаксис: ```cpp ifdef macro_name statement1; statement2; statement3; . . . statementN; endif ``` Если макрос с именем «macroname» определен, тогда блок операторов будет выполняться нормально, но если он не определен, компилятор просто пропустит этот блок операторов. ### Другие директивы: Помимо вышеуказанных директив есть еще две директивы, которые обычно не используются. Это: 1. \##### `#undef` Директива: Директива `#undef` используется для определения существующего макроса. Эта директива работает как: ##### Синтаксис: `#undef LIMIT` Использование этого оператора будет определять неопределенный существующий макрос LIMIT. После этого утверждения каждый оператор `#ifdef LIMIT` будет оценивать значение false. 2. \##### # `#pragma` директива: Эта директива является директивой специального назначения и используется для включения или отключения некоторых функций. Этот тип директив специфичен для компилятора, т. Е. Они варьируются от компилятора к компилятору. Некоторые из директив `#pragma` обсуждаются ниже: ##### `#pragma startup` и `#pragma exit` : Эти директивы помогают нам определить функции, которые необходимы для запуска до запуска программы (до того, как элемент управления переходит к main ()) и непосредственно перед выходом программы (как раз перед возвратом элемента управления из main ()). ```cpp #include void func1(); void func2(); #pragma startup func1 #pragma exit func2 void func1() { printf("Inside func1() "); } void func2() { printf("Inside func2() "); } int main() { printf("Inside main() "); return 0; } ``` Вывод: `Inside func1() Inside main() Inside func2()` Вышеприведенный код будет выдавать результат, указанный ниже при запуске на компиляторах GCC: Вывод: `Inside main()` Это происходит потому, что GCC не поддерживает запуск #pragma или выход. Однако вы можете использовать приведенный ниже код для аналогичного вывода на компиляторах GCC. ```cpp #include void func1(); void func2(); void __attribute__((constructor)) func1(); void __attribute__((destructor)) func2(); void func1() { printf("Inside func1()\n"); } void func2() { printf("Inside func2()\n"); } int main() { printf("Inside main()\n"); return 0; } ``` ##### `#pragma warn` Директива: Эта директива используется, чтобы скрыть предупреждающее сообщение, которое отображается во время компиляции. Мы можем скрыть предупреждения, как показано ниже: ##### `#pragma warn -rvl` : Эта директива скрывает предупреждение, которое возникает, когда функция, которая должна возвращать значение, не возвращает значение. ##### `#pragma warn -par` : Эта директива скрывает предупреждение, которое возникает, когда функция не использует переданные ей параметры. ##### `#pragma warn -rch` : Эта директива скрывает предупреждение, которое возникает, когда код недостижим. Например: любой код, написанный после оператора return в функции, недоступен.