Директивы условной компиляции #if, #ifdef, #ifndef

 

Эти директивы позволяют исключить компиляцию отдельных частей программы в зависимости от проверяемого условия (условие – константное выражение).

 

#if условие текст_для_if [ #elif условие1 текст1 ] [ #elif условие2 текст2 ] ... [ #else текст_для_else ] #endif Проверяется условие. Если оно истинно (¹0), то в компилируемый текст включается текст_для_if; в противном случае (=0) вычисляется условие1, если оно ложно (=0), вы­числяется условие2 и т.д. В компилируемый текст включа­ется текст, соответствующий усло­вию, которое оказалось истинным. Если все условия ложны, то включается текст_для_else (либо ничего не включается в случае отсутствия #else).

Здесь квадратные скобки означают необязательность элемента синтаксической конструкции.

Таким образом, препроцессор обработает только один текст (либо ни одного), выделенный директивами #if, #elif. Количество директив #elif – произвольное.

 

Рассмотрим пример с условным включением различных версий заголовочного файла:

 

#if VER == 1

#define INCFILE "vers1.h"

#elif VER == 2

#define INCFILE "vers2.h"

 

... // И так далее

 

#else

#define INCFILE "vers.h"

#endif

 

#include INCFILE

 

Другое назначение директивы #if – временно закоммен ­ тировать фрагмент кода. Поскольку допускается вложенность директив (при недопустимости вложенности многострочных комментариев), такой способ весьма удобен:

 

#if 0

... // Исключаемый код

#endif

#ifdef идентификатор // текст #endif Текст включается компилятором, если определён к текущему моменту с помощью #define идентификатор (он является препроцессорным).

 

В директиве #ifndef проверяется обратное условие (если идентификатор не определён).

 

! Действие директив #ifdef и #ifndef распространяется до первой директивы #elif, #else, #endif.

 

Пример включения контрольной печати при отладке:

 

#define DEBUG

...

#ifdef DEBUG

cout << "Отладочная печать";

#endif

 

Убрав директиву #define DEBUG, сразу отключаем все отладочные распечатки.

 

Рассмотрим пример защиты от повторного включения файлов (программа состоит из нескольких модулей, в каждом из которых препроцессорно включается один и тот же заголовочный файл; модули объединяются в общий текст). Аналогом этого использования директив #ifndef... #define... #endif в Microsoft Visual Studio является #pragma once.

 

// Файл myheader.h

#ifndef MYHEADER_INCLUDED

#define MYHEADER_INCLUDED

... // Текст заголовочного файла

 

#endif

 

// Файл file1.cpp

#include "myheader.h"

... // Текст файла file1.cpp

 

// Файл file2.cpp

#include "myheader.h"

... // Текст файла file2.cpp

 

Здесь MYHEADER_INCLUDED – зарезервированный для заголовочного файла препроцессорный идентификатор, который должен быть уникальным (не должен встречаться в других текстах многомодульной программы). При первом использовании директивы #include "myheader.h" произойдёт включение текста файла myheader.h, препроцессорный идентификатор MYHEADER_INCLUDED определится директивой #define, и при последующих директивах #include файл повторно вставляться не будет.

 

Операция defined – унарная препроцессорная.

Формат использования операции:

defined операнд или defined (операнд)

Выражение – результат операции – истинно, если иденти­фикатор операнда до этого определён директивой #define:

 

#if defined операнд º #ifdef операнд

 

Операцию defined добно использовать, например, при сложном условии выбора:

 

#if defined (A) &&!defined (B) ... #endif   #ifdef A #ifndef B ... #endif #endif

Текст передаётся компилятору в случае определения идентификатора А как препроцессорного и не определения В.

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: