freeCodeCamp/guide/russian/cplusplus/preprocessors/index.md

160 lines
11 KiB
Markdown
Raw Normal View History

2018-10-12 20:00:59 +00:00
---
title: Preprocessors
localeTitle: Препроцессоры
---
## Препроцессоры в C / CPP
Как видно из названия, препроцессоры - это программы, которые обрабатывают наш исходный код перед компиляцией. Существует несколько шагов, связанных с написанием программы и выполнением программы на C / C ++. Давайте посмотрим на эти шаги, прежде чем мы начнем узнавать о препроцессорах.
![Img](https://i.imgur.com/Pb0aTkV.png)
Вы можете увидеть промежуточные шаги на приведенной выше диаграмме. Исходный код, написанный программистами, хранится в файле program.c. Затем этот файл обрабатывается препроцессорами, а файл расширенного исходного кода создается с именем program. Этот расширенный файл компилируется компилятором и создается файл объектного кода с именем program.obj. Наконец, компоновщик связывает этот файл объектного кода с объектным кодом библиотечных функций для генерации исполняемого файла program.exe.
Препроцессорные программы предоставляют директивы препроцессоров, которые сообщают компилятору предварительно обработать исходный код перед компиляцией. Все эти директивы препроцессора начинаются с символа `#` (хеш). Этот символ ('#') в начале инструкции в программе C / C ++ указывает, что это предпроцессорная директива. Мы можем разместить эти предпроцессорные директивы в любой нашей программе. Примерами некоторых препроцессорных директив являются: `#include` , `#define` , `#ifndef` и т. Д.
### Типы предпроцессорных директив:
1. макрос
2. Включение файлов
3. Условная компиляция
4. Другие директивы
### Макросы:
Макросы являются частью кода в программе, которому дано какое-то имя. Всякий раз, когда это имя встречается компилятором, компилятор заменяет это имя фактическим фрагментом кода. Директива `#define` используется для определения макроса.
```cpp
#include<iostream>
#define LIMIT 3
int main()
{
for(int i=0; i < LIMIT; i++)
{
std::cout<<i<<" " ;
}
return 0;
}
```
Вывод:
`0 1 2`
В вышеприведенной программе, когда компилятор выполняет слово `LIMIT` он заменяет его на 3. Слово `LIMIT` в определении макроса называется макромодом, а «3» - расширением макроса.
В конце определения макроса не должно быть запятой (';'). Определения макросов не нуждаются в полуточке.
### Включение файла:
Этот тип предпроцессорной директивы сообщает компилятору включить файл в программу исходного кода. Существует два типа файлов, которые могут быть включены пользователем в программу:
* \#### Файл заголовка или стандартные файлы: Эти файлы содержат определение предопределенных функций, таких как printf (), ... scanf () и т. Д. Эти файлы должны быть включены для работы с этими функциями. ... Различные функции объявляются в разных файлах заголовков. Например ... стандартные операции ввода-вывода находятся в файле «iostream», тогда как функции, которые ... выполняют строковые операции, находятся в файле «string».
#### Синтаксис:
`#include< file_name >` где 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<stdio.h>
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<stdio.h>
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 в функции, недоступен.