Директивы препроцессора в C++

Директивы препроцессораПрепроцессор — уникальная особенность C++. В C++ существуют такие шаги, как компиляция, компоновка и выполнение для типичной программы. На самом деле, есть еще много других функций в программе на C++, которые необходимо обработать перед передачей программы на компиляцию.

Для этого проводится специальный этап, называемый предварительной обработкой. Предварительная обработка выполняется до процесса компиляции, и специальные функции предварительно обрабатываются. В результате получается расширенная программа на С++, которая затем передается компилятору.

Специальные функции для предварительной обработки идентифицируются с помощью объекта, называемого «Директива препроцессора». Эти директивы препроцессора сообщают компилятору, что определенная информация в программе C++, помеченная директивами препроцессора, должна быть предварительно обработана перед компиляцией.

Обратите внимание, что в C++ все директивы препроцессора начинаются с символа «#». В тот момент, когда препроцессор (часть компилятора) встречает символ #, информация, следующая за символом #, предварительно обрабатывается перед передачей программы компилятору.

В отличие от других операторов C++, директивы препроцессора не заканчиваются точкой с запятой.

Директивы включения файлов

#include

Директива включения файлов #include позволяет нам включать другие файлы в нашу исходную программу. Мы можем включить в нашу программу любой заголовочный файл, содержащий определения различных предопределенных функций, используя эти функции. Мы можем включить файлы заголовков в нашу программу, используя следующий синтаксис:

Пример: #include <iostream>

Заголовок iostream содержит функции, необходимые для потоковой передачи данных ввода/вывода, такие как cout, cin и т. д.

По мере того, как наши программы становятся больше или функциональность усложняется, мы можем захотеть разделить нашу программу на несколько файлов или импортировать функциональность из других файлов. В этом случае мы используем пользовательские файлы. Чтобы включить пользовательские файлы в нашу программу, мы можем использовать следующий синтаксис директивы #include:

Читать также:  Многомерные массивы в C++

Пример: #include «vector_int.h»

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

В приведенном ниже примере кода показано использование директивы #include:

Это пример, демонстрирующий директиву включения #include.

Как показано выше, мы использовали директиву #include, чтобы включить функциональность заголовка <iostream> в нашу программу.

Директивы определения макросов

#define

Директива #define используется для определения символических констант или макросов в программе на C++.

Общая форма директивы #define следующая:

Когда препроцессор встречает макрос в программе, препроцессор заменяет этот макрос кодом, определенным с помощью директивы #define, прежде чем код будет передан компилятору.

В приведенном ниже примере кода показана символическая константа RADIUS, определенная с помощью директивы #define:

Вывод данных:

Как показано в программе, мы можем использовать символическую константу RADIUS в нашем коде, и она будет заменена значением, определенным для нее с помощью директивы #define.

Мы можем использовать директиву #define для определения правильного кода функции. Эти функции обычно являются небольшими функциями.

Пример показан ниже:

Вывод данных:

Здесь с помощью директивы #define мы определили функцию REC_AREA, которая принимает два аргумента, т.е. длину и ширину, и вычисляет площадь прямоугольника. В основной функции мы просто используем этот макрос и передаем ему два аргумента, для получения площади прямоугольника.

#undef

Макросы в программе, определенные с помощью директивы #define, остаются в силе до тех пор, пока они не будут определены с помощью директивы #undef. Как только программа обнаружит #undef, последующее использование макроса (не определенного #undef) приведет к ошибке компиляции.

Читать также:  Двусвязный список структуры данных в C++

В приведенной выше программе, если мы просто введем оператор #undef REC_AREA после объявлений целых чисел, программа выдаст ошибку компиляции.

Директивы условной компиляции

Помимо описанных выше директив, C++ также предоставляет следующие директивы, которые можно использовать для условной компиляции кода. Эти директивы можно использовать в аналогичных строках оператора if-else C++.

Например, мы можем установить DEBUG для программы в положение ON или OFF, используя эти условные директивы.

Некоторые из директив условной компиляции, представленных в C++, включают в себя:

  • #if
  • #elif
  • #endif
  • #ifdef
  • #ifndef
  • #else

В приведенной ниже программе показано использование директив условной компиляции в программе на C++:

Вывод данных:

В приведенной выше программе мы используем директиву #ifdef — #endif для определения DEBUG для программы. Затем мы отменили определение функции макроса MAX с помощью директивы #undef. Директива условной компиляции #ifdef — #endif проверяет, установлен ли DEBUG, и если он установлен, то печатает несколько сообщений в программе.

Операторы # и ##

Операторы # и ## — это два специальных оператора, которые соответственно используются для преобразования текстового токена в отображаемую строку и объединения двух токенов.

Ниже приведен пример, демонстрирующий работу этих операторов:

Вывод данных:

В приведенной выше программе мы определяем MKSTR с аргументом x. У него тело №x. Когда мы печатаем этот MKSTR с использованием аргумента «Hello World», мы видим, что из-за #x аргумент преобразуется в строку и отображается на выходе.

Читать также:  Арифметические операторы в языке программирования Паскаль

Затем мы определили функцию concat с двумя аргументами a и b. В теле указываем a##b. Выражение a##b равно ab. Таким образом, в основной функции, когда мы вызываем concat(x,y), она на самом деле вычисляет значение xy, равное целочисленной переменной, которую мы определили.

Другие директивы

#error

Общий синтаксис директивы #error:

#line

#line говорит компилятору изменить номер строки и имя файла, хранящиеся внутри компилятора, на заданный номер строки и имя файла.

digit_sequence может быть целочисленной константой.

Пример: #line 200 test.c

В приведенном выше примере для внутреннего сохраненного номера строки установлено значение 200, а имя файла изменено на test.c.

#pragma

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

Предопределенные макросы

C++ также определяет множество предопределенных макросов, которые могут использоваться программистами.

Некоторые из этих макросов приведены в таблице ниже:

Предопределенный макрос Описание
__FILE__ Текущее имя файла компилируемой программы
__DATE__ Дата перевода исходного кода в объектный код в формате месяц/день/год
__TIME__ Время в формате час:минута:секунда, когда программа компилируется
__LINE__ Текущий номер строки компилирующейся программы
__cplusplus Целочисленная константа, определенная для каждой версии компилятора.

Следующая программа демонстрирует эти макросы:

Вывод данных:

Вывод программы выше соответствует объяснению предопределенных макросов выше и не требует пояснений.

Итог

Директивы препроцессора помогают нам писать более эффективные программы и в некоторой степени более читаемые программы. Директивы условной компиляции также позволяют нам различными способами разветвлять вывод нашей программы.

В следующей статье мы поговорим о многопоточности, а также приведем примеры для лучшего понимания.

С Уважением, МониторБанк

Добавить комментарий