Директивы #if, #elif, #else и #endif (C/C++)
Директива #if с директивами #elif, #else и #endif управляет компиляцией частей исходного файла. Если написанное выражение (после #if) имеет ненулевое значение, группа строк сразу после директивы #if хранится в модуле перевода.
грамматики
if-line :
#if констант-выражение
идентификатор #ifdef
идентификатор #ifndef
elif-parts :
текст с элифовой линией
текст elif-parts elif-line
elif-line :
#elif констант-выражение
else-part :
Текст в другой строке
else-line :
#else
endif-line :
#endif
Замечания
Каждая директива #if в исходном файле должна соответствовать закрывающей директиве #endif . Любое количество директив #elif может отображаться между директивами #if и #endif , но в большинстве случаев допускается одна директива #else . Директива #else, если она присутствует, должна быть последней директивой перед #endif.
Директивы #if, #elif, #else и #endif могут вложены в текстовые части других директив #if. Каждая вложенная директива #else, #elif или #endif принадлежит ближайшей предыдущей директиве #if.
Все директивы условной компиляции, такие как #if и #ifdef, должны соответствовать закрывающей директиве #endif до окончания файла. В противном случае создается сообщение об ошибке. Если директивы условной компиляции содержатся во включаемых файлах, они должны удовлетворять одинаковым условиям: в конце включаемого файла не должно оставаться непарных директив условной компиляции.
Замена макросов выполняется в части строки, которая следует #elif команде, поэтому вызов макроса можно использовать в констант-выражении.
Препроцессор выбирает один из указанных вхождения текста для дальнейшей обработки. Блок, указанный в тексте , может быть любой последовательностью текста. Он может занимать несколько строк. Обычно текст — это программный текст , который имеет значение для компилятора или препроцессора.
Препроцессор обрабатывает выделенный текст и передает его компилятору. Если текст содержит директивы препроцессора, препроцессор выполняет эти директивы. Компилируются только текстовые блоки, выбранные препроцессором.
Препроцессор выбирает один текстовый элемент, оценивая константное выражение после каждой #if или директивы #elif, пока не находит истинное (ненулевое) константное выражение. Он выбирает весь текст (включая другие директивы препроцессора, начиная с#) до связанного #elif, #else или #endif.
Если все вхождения констант-выражения являются ложными или если директивы #elif не отображаются, препроцессор выбирает блок текста после предложения #else. Если нет предложения #else, а все экземпляры константного выражения в блоке #if имеют значение false, текстовый блок не выбран.
Константное выражение — это целочисленное константное выражение с этими дополнительными ограничениями:
- Выражения должны иметь целочисленный тип и могут включать только целые константы, константы символов и определенный оператор.
- Выражение не может использовать sizeof или оператор приведения типа.
- Целевая среда может не представлять все диапазоны целых чисел.
- Перевод представляет тип так же, как и тип intlong , и тот же способ, что unsigned long и unsigned int .
- Транслятор может преобразовывать символьные константы в набор кодовых значений, отличающийся от набора для целевой среды. Чтобы определить свойства целевой среды, используйте приложение, созданное для этой среды, для проверка значений LIMITS. Макросы H.
- Выражение не должно запрашивать среду и оставаться изолированным от сведений о реализации на целевом компьютере.
Операторы препроцессора
архитектура
Определяемый оператор препроцессора можно использовать в специальных константных выражениях, как показано в следующем синтаксисе:
defined(identifier)
определенныйидентификатор
Это константное выражение считается истинным (ненулевое), если идентификатор определен в данный момент. В противном случае условие не выполняется (false, значение равно 0). Идентификатор, определенный как пустой текст, считается определенным. Определенный оператор можно использовать в #if и директиве #elif, но нигде.
В следующем примере директивы #if и #endif управляют компиляцией одного из трех вызовов функций:
#if defined(CREDIT) credit(); #elif defined(DEBIT) debit(); #else printerror(); #endif
Вызов функции credit компилируется, если определен идентификатор CREDIT . Если определен идентификатор DEBIT , компилируется вызов функции debit . Если ни один из этих идентификаторов не определен, компилируется вызов функции printerror . Оба CREDIT и credit являются уникальными идентификаторами в C и C++, так как их варианты отличаются.
В следующем примере в операторах условной компиляции используется ранее определенная символьная константа с именем DLEVEL .
#if DLEVEL > 5 #define SIGNAL 1 #if STACKUSE == 1 #define STACK 200 #else #define STACK 100 #endif #else #define SIGNAL 0 #if STACKUSE == 1 #define STACK 100 #else #define STACK 50 #endif #endif #if DLEVEL == 0 #define STACK 0 #elif DLEVEL == 1 #define STACK 100 #elif DLEVEL > 5 display( debugptr ); #else #define STACK 200 #endif
В первом блоке #if показаны два набора вложенных #if, #else и директив #endif. Первый набор директив обрабатывается только в том случае, если выполняется условие DLEVEL > 5 . В противном случае операторы после обработки #else .
Директивы #elif и #else во втором примере используются для выбора одного из четырех вариантов на основе значения DLEVEL . Константе STACK присваивается значение 0, 100 или 200 в зависимости от определения константы DLEVEL . Если DLEVEL больше 5, то компилируется оператор
#elif DLEVEL > 5 display(debugptr);
компилируется и STACK не определен.
Условная компиляция обычно используется для предотвращения нескольких включений одного и того же файла заголовка. В C++, где классы часто определяются в файлах заголовков, такие как этот, можно использовать для предотвращения нескольких определений:
/* EXAMPLE.H - Example header file */ #if !defined( EXAMPLE_H ) #define EXAMPLE_H class Example < //. >; #endif // !defined( EXAMPLE_H )
Предыдущий код проверяет, определена ли символьная константа EXAMPLE_H . Если да, файл уже включен и не нуждается в повторной обработке. Если нет, константа EXAMPLE_H определяется, чтобы пометить файл EXAMPLE.H как уже обработанный.
__has_include
Visual Studio 2017 версии 15.3 и более поздних версий: определяет, доступен ли заголовок библиотеки для включения:
#ifdef __has_include # if __has_include() # include # define have_filesystem 1 # elif __has_include() # include # define have_filesystem 1 # define experimental_filesystem # else # define have_filesystem 0 # endif #endif
Как работает оператор else if и в чем отличие от if?
Достаточно рассмотреть простой пример, чтобы понять, в чем заключается разница.
int x = 0; if ( x == 0 ) < System.out.printline( "x = " + x ); ++x; >else if ( x == 1 ) < System.out.printline( "x = " + x ); ++x; >else if ( x == 2 ) < System.out.printline( "x x = " + x ); ++x; >if ( x == 1 ) < System.out.printline( "x = " + x ); ++x; >if ( x == 2 ) < System.out.printline( "x mt24"> )" data-controller="se-share-sheet" data-se-share-sheet-title="Поделиться ссылкой на ответ" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter " data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start">Поделиться )" title="">Улучшить ответ )">изменён 8 ноя 2016 в 12:25 Nick Volynkin♦ 34k 25 золотых знаков 130 серебряных знаков 222 бронзовых знака ответ дан 8 ноя 2016 в 11:40 Vlad from MoscowVlad from Moscow 44.8k 3 золотых знака 38 серебряных знаков 89 бронзовых знаков