#include строка-лексем
имеет вид, соответствующий ни первой, ни второй управляющей строке, то лексемы препроцессора, заданные в этой команде обрабатываются как обычный текст. В результате должна получиться команда, вид которой соответствует одному из приведенных. Она и будет выполнена как положено.
Команда #include может быть в файле, который сам появился в результате выполнения другой команды #include.
Реализация может накладывать ограничение на глубину вложенности команды #include во входных файлах программы, которые приходится читать для выполнения первоначальной команды #include в одном из входных файлов.
R.16.5 Условная трансляция
С помощью препроцессора можно организовать условную трансляцию программы. Синтаксически это задается следующим образом:
условное:
часть-if части-elif opt часть-else opt строка-endif
часть-if:
строка-if текст
строка-if:
# if выражение-константа
# ifdef идентификатор
# ifndef идентификатор
части-elif:
строка-elif текст
части-elif строка-elif текст
строка-elif:
# elif выражение-константа
часть-else:
строка-else текст
строка-else:
# else
строка-endif:
# endif
Константные выражения в #if и #elif (если эти части есть) вычисляются в порядке их задания в тексте до тех пор, пока одно из них не окажется отличным от нуля. Операторы С++, следующие за строкой, в которой выражение оказалось равным нулю, не транслируются. Команды препроцессора, идущие за этой строкой игнорируются. После того, как найдена команда с ненулевым значением выражения, текст всех последующих частей #elif и #else (т.е. операторы C++ и команды препроцессора) игнорируется. Текст, относящийся к первой команде с ненулевым значением выражения подлежит обычной препроцессорной обработке и трансляции. Если значения всех выражений, указанных в #if и #elif, оказались равными нулю, тогда обычной обработке подлежит текст, относящийся к #else.
В выражении-константе, которое встретилось в #if или #elif можно использовать унарную операцию defined, причем в двух вариантах:
defined идентификатор
или
defined (идентификатор)
Если эта операция применяется к идентификатору, который был определен с помощью команды #define, и если это определение не было отменено командой #undef, то результат равен 1, иначе результат равен 0. Сам идентификатор defined нельзя переопределить, нельзя и отменить его определение.
После применения операций defined происходит раскрытие всех всех макроопределений, имеющихся в константном выражении см. §R.16.3. В результате должно получиться целочисленное выражение-константа, отличающееся от определения в §R.5.19 тем, что типы int и unsigned int рассматриваются как long и unsigned long соответственно, а кроме того в этом выражении не должно быть операций приведения, sizeof или элемента перечисления.
Управляющая строка
#ifdef идентификатор
эквивалентна строке
#if defined идентификатор
а управляющая строка
#ifndef идентификатор
эквивалентна строке
#if !defined идентификатор
Конструкции, задающие условную трансляцию, могут быть вложенными, но реализация может накладывать ограничение на глубину вложенности этих конструкций.
R.16.6 Управление строками
Для удобства написания программ, порождающих текст на С++, введена управляющая строка вида:
#line константа "имяфайла" opt
Она задает значение предопределенному макроимени __LINE__ (§R.16.10), которое используется в диагностических сообщениях или при символической отладке; а именно: номер следующей строки входного текста считается равным заданной константе, которая должна быть десятичным целым числом. Если задано "имяфайла", то значение макроимени __FILE__ (§R.16.10) становится равным имени указанного файла. Если оно не задано, __FILE__ не меняет своего значения.
Макроопределения в этой управляющей строке раскрываются до выполнения самой команды.
R.16.7 Команда error
Строка вида:
#error строка-лексем
заставляет реализацию выдать диагностическое сообщение, состоящее из заданной последовательности лексем препроцессора.
R.16.8 Команда pragma
Строка вида:
#pragma строка-лексем
заставляет реализацию вести себя некоторым определенным образом при условии что реализация "понимает" эту строку. Любая нераспознанная строка #pragma игнорируется.
R.16.9 Пустая директива
Команда препроцессора вида
#
не оказывает никакого действия.
R.16.10 Предопределенные макроимена