Препроцессоры - это директивы, которые дают инструкции компилятору для предварительной обработки информации до начала фактической компиляции.
Все директивы препроцессора начинаются с #, и перед директивой препроцессора на строке могут появляться только символы пробела. Директивы препроцессора не являются инструкциями C ++, поэтому они не заканчиваются точкой с запятой (;)
.
Вы уже видели директиву #include
во всех примерах. Этот макрос используется для включения файла заголовка в исходный файл.
Существует ряд препроцессорных директив, поддерживаемых C ++ типа #include, #define, #if, #else, #line
и т. д. Давайте посмотрим важные директивы -
Префикс #define
Директива префикса #define
создает символические константы. Символьная константа называется макросом, а общая форма директивы:
#define macro-name replacement-text
Когда эта строка появляется в файле, все последующие вхождения макроса в этот файл будут заменены заменяющим текстом перед компиляцией программы. Например:
#include <iostream>
using namespace std;
#define PI 3.14159
int main () {
cout << "Value of PI :" << PI << endl;
return 0;
}
Теперь давайте сделаем предварительную обработку этого кода, чтобы увидеть результат, предполагающий, что у нас есть файл исходного кода. Поэтому давайте скомпилируем его с опцией -E и перенаправим результат на test.p
. Теперь, если вы проверите test.p
, у него будет много информации, а внизу вы найдете значение, замененное следующим образом:
$gcc -E test.cpp > test.p
...
int main () {
cout << "Value of PI :" << 3.14159 << endl;
return 0;
}
Функциональные макросы
Вы можете использовать #define
для определения макроса, который будет принимать аргумент следующим образом:
#include <iostream>
using namespace std;
#define MIN(a,b) (((a)<(b)) ? a : b)
int main () {
int i, j;
i = 100;
j = 30;
cout <<"The minimum is " << MIN(i, j) << endl;
return 0;
}
Если мы скомпилируем и запустим код выше, это приведет к следующему результату:
The minimum is 30
Условная компиляция
Существует несколько директив, которые можно использовать для компиляции выборочных частей исходного кода вашей программы. Этот процесс называется условной компиляцией.
Конструкция условного препроцессора очень похожа на структуру выбора if
. Рассмотрим следующий код препроцессора:
#ifndef NULL
#define NULL 0
#endif
Вы можете скомпилировать программу для цели отладки. Вы также можете включить или отключить отладку с использованием одного макроса следующим образом:
#ifdef DEBUG
cerr <<"Variable x = " << x << endl;
#endif
Это приводит к компиляции инструкции cerr в программе, если символьная константа DEBUG
была определена до директивы #ifdef DEBUG
. Вы можете использовать #if 0 statment
, чтобы прокомментировать часть программы следующим образом:
#if 0
code prevented from compiling
#endif
Попробуем следующий пример:
#include <iostream>
using namespace std;
#define DEBUG
#define MIN(a,b) (((a)<(b)) ? a : b)
int main () {
int i, j;
i = 100;
j = 30;
#ifdef DEBUG
cerr <<"Trace: Inside main function" << endl;
#endif
#if 0
/* This is commented part */
cout << MKSTR(HELLO C++) << endl;
#endif
cout <<"The minimum is " << MIN(i, j) << endl;
#ifdef DEBUG
cerr <<"Trace: Coming out of main function" << endl;
#endif
return 0;
}
Если мы скомпилируем и запустим код выше, это приведет к следующему результату:
The minimum is 30
Trace: Inside main function
Trace: Coming out of main function
Операторы # и ##
Операторы препроцессора # и ## доступны в C ++ и ANSI / ISO C. Оператор # заставляет токен заменяющего текста преобразовываться в строку, окруженную кавычками.
Рассмотрим следующее макроопределение -
#include <iostream>
using namespace std;
#define MKSTR( x ) #x
int main () {
cout << MKSTR(HELLO C++) << endl;
return 0;
}
Если мы скомпилируем и запустим код выше, это приведет к следующему результату:
HELLO C++
Посмотрим, как это работает. Легко понять, что препроцессор C ++ превращает строку:
cout << MKSTR(HELLO C++) << endl;
Над строкой будет переведена следующая строка:
cout << "HELLO C++" << endl;
Оператор ## используется для объединения двух токенов.
#define CONCAT( x, y ) x ## y
Когда CONCAT появляется в программе, его аргументы конкатенируются и используются для замены макроса. Например, CONCAT (HELLO, C ++)
заменяется на HELLO C ++
в программе следующим образом.
#include <iostream>
using namespace std;
#define concat(a, b) a ## b
int main() {
int xy = 100;
cout << concat(x, y);
return 0;
}
Если мы скомпилируем и запустим код выше, это приведет к следующему результату:
100
Посмотрим, как это работает. Легко понять, что препроцессор C ++ преобразует:
cout << concat(x, y);
Над строкой будет преобразована следующая строка:
cout << xy;
Предопределенные макросы C ++
C ++ предоставляет ряд предопределенных макросов, упомянутых ниже -
__LINE__
Он содержит текущий номер строки программы при компиляции.
__FILE__
Он содержит текущее имя файла программы при компиляции.
__DATE__
Он содержит строку формы month / day / year
, которая является датой перевода исходного файла в объектный код.
__TIME__
Это содержит строку формы hour: minute: second
- время, в которое была скомпилирована программа.
Давайте посмотрим пример для всех вышеперечисленных макросов:
#include <iostream>
using namespace std;
int main () {
cout << "Value of __LINE__ : " << __LINE__ << endl;
cout << "Value of __FILE__ : " << __FILE__ << endl;
cout << "Value of __DATE__ : " << __DATE__ << endl;
cout << "Value of __TIME__ : " << __TIME__ << endl;
return 0;
}
Если мы скомпилируем и запустим код выше, это приведет к следующему результату:
Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48
0 комментариев