Первая (сокращённая) форма директивы #if в общем виде записывается так:
#if константное_выражение
последовательность операторов (блок 1)
#endif
Выражение, записанное в директиве # if, вычисляется на этапе компиляции, а не во время выполнения, как в обычном операторе if. Поэтому оно должно быть составлено из констант и макроимён, определённых с помощью директивы define, ине должно содержать переменных. Если выражение истинно (отлично от нуля), то строки, записанные между #if и #endif остаются в тексте программы и затем будут компилироваться, а #if и #endif исключаются из текста. В противном случае, если значение выражения false (равно нулю), то последовательность опереаторов исключается вместе с #if и #endif из текста программы и не будет компилироваться. Например,
#define MAX 50
… /* здесь размещаются некоторые операторы */
#if MAX>100
cout<<” This text is compiled”;
… /* Здесь могут быть другие операторы */
#endif
… /* Здесь программа продолжается */
В результате препроцессорной обработки оператор
cout<<” This text is compiled”;
и, возможно, записанные в этом блоке другие операторы, не включаются в программу и компилироваться не будут, так как условие 50>100 ложно. Если значение макроса MAX изменить, например,
#define MAX 150,
то оператор вывода будет включён для компиляции, так как 150>100.
Вторая (полная) форма директивы #if в общем виде записывается так:
#if константное_выражение
последовательность операторов (блок1)
#else
последовательность операторов (блок2)
#endif
По аналогии с полной формой обычного оператора if в зависимости от значения константного выражения в компилируемую программу будет включён блок1 или блок2.
Для построения конструкции с вложенной директивой # if (лесенки if-else-if) используется директива #elif:
#if константное_выражение1
последовательность операторов (блок1)
#elif константное_выражение2
последовательность операторов (блок2)
#elif константное_выражение3
последовательность операторов (блок3)
…
#elif константное_выражениеN
последовательность операторов (блокN)
#else
последовательность операторов (блок(N+1))
#endif
Если истинно i- е константное выражение, то для компиляции включается i -й блок, и остальные выражения не проверяются. В противном случае вычисляется и проверяется следующее выражение. Если все выражения ложны, то используется (N+1)- й блок, если есть директива #else. Если #else отсутствует, то в случае ложности всех выражений ни один из блоков в компиляции не участвует.
Как и для оператора if, возможны другие вложенные конструкции директивы # if, например, в качестве любого из блоков может быть полная или сокращённая форма директивы # if.
Упражнение. Привести пример полной формы директивы # if и вложенной директивы #if.
3.2. Директивы #ifdef и #ifndef.
Другой метод условной компиляции заключается в использовании директив #ifdef и #ifndef. Стандартный их вид следующий:
#ifdef имя_макроса
последовательность операторов
#endif
или
#ifndef имя_макроса
последовательность операторов
#endif
В первом варианте, если имя макроса определено ранее директивой #define, то последовательность операторов, стоящих между #ifdef и #endif, будет компилироваться. Во втором варианте последовательность операторов будет компилироваться., если указанный макрос не определён. Для этих директив также можно использовать #else, но не #elif. Их можно вкладывать друг в друга.
Пример.
#define M 10
…
#ifdef M
…
cout<<”Макрос М определён”;
#else
…
cout<<”Макрос М не определён”;
#endif
Так как макрос M определён, то компилироваться будет первый блок.
Существует ещё один способ узнать, определён ли макрос. В сочетании с директивой #if можно использовать следующий оператор времени компиляции:
defined имя_макроса
Если имя_макроса определено, то выражение станет истинным, в противном случае будет ложным. Например, для проверки, определён ли макрос М, можно записать
#if defined M
…
#endif
И если он определён, то операторы, записанные под #if, будут компилироваться. Перед defined можно поместить операцию отрицания, например,
#if!defined M
…
#endif
Фрагмент под #if будет компилироваться, только если макрос М не определён.
Упражнения, тесты
1. Дан код:
#define MACR(x) (x%10+5) //1
int k=39; printf(“%d”, MACR(k+1)); //2
Что будет выведено?
Варианты ответов:
1) 5; 2) 45; 3) 44; 4) 9; 5) Ошибка в //1; 6) Ошибка в //2.
2. Дан код:
#define writeln(v) //1
#int k=40; //2
cout<<(#v)<<” “<<k; //3
writeln (k); //4
В каких строках есть ошибки. Что будет выведено, если исправить ошибки?
3. Дан код:
#define ONE 1 //1
# if ONE>1 //2
cout<<ONE; //3
#undef ONE //4
#endif //5
#ifdef ONE //6
#define TWO 2 //7
#else //8
#define TWO 22 //9
cout<<” “<<TWO; //10
#endif //11
Что будет выведено?
Варианты ответов:
1) 1 2 2) 1 22 3) 2 4) 22 5) ошибка (указать, в какой (//1 — //11) строке (строках))
4. Выберите номера правильных утверждений:
1) Подключаемый с помощью директивы компиляции #include файл обязательно должен быть оформлен по правилам записи функций.
2) В подключаемом с помощью директивы компиляции #include файле могут быть только объявления переменных. Никакие выполняемые операторы в таком файле не должны быть.
3) В подключаемом с помощью директивы компиляции #include файле может быть любая часть программы, не обязательно оформленная в виде функции.
4) В подключаемом с помощью директивы компиляции #include файле могут быть только директивы компиляции. Объявления переменных и выполняемые операторы в таком файле не должны быть.
5) В подключаемом с помощью директивы компиляции #include файле можно записать только прототипы функций, а их тексты записываем в основном файле.
5. Даны следующие директивы компиляции:
#include “myfile.h” //1
#include <stdio> //2
#define IncFile “AddFile1.h” //3
#include IncFile //4
В каких из них есть ошибки? Чем отличается подключение указанных здесь файлов?
6. 6.1.Дан код:
#define c 2 //1
int k=5; //2
#if k>5 //3
cout<< c <<”Yes”; //4
#else cout<<”No”; //5
#endif //6
В каких строках (//1 — //6) есть ошибки? Объяснить их. Если ошибок нет, что будет выведено?
6.2. Сравните приведенный выше код со следующим:
const c=2; //1
int k=5; //2
if k>5 //3
cout<< c <<”Yes”; //4
else cout<<”No”; //5
endif //6
В каких строках (//1 — //6) есть ошибки? Объяснить их. Если ошибок нет, что будет выведено?
7. Дан код:
#define N 10 //1
#ifndef N //2
#define N 20 //3
cout<< N; //4
#endif //5
cout<<” “<<N; //6
Что будет выведено?
Варианты ответов:
1) 10 2) 20 3) 10 10 4) 20 20 5)10 20 6) 20 20
7) ошибка (указать, в какой (//1 — //6) строке (строках))
8. Дан код:
#define N 10 //1
#define K 20 //2
#if!defined(N) //3
#define N 40 //4
cout<< N <<” “<<K; //5
#elif K<50 //6
cout<<” “<<(N+K); //7
#else //8
cout<<” “<<(N-K); //9
#endif //10
cout<<” “<<N; //11
Что будет выведено?
Варианты ответов:
1) 30 2) 60 3) 10 40 4) -10 5) 20 6) 40 20 60 10 7) 30 10