Командные Строки Компилятора

Компилятор языка C++ содержит препроцессор, способный выполнять макроподстановки, условную компиляцию и включение именованных файлов. Строки, начинающиеся с #, относятся к препроцессору. Эти строки имеют независимый от остального языка синтаксис; они могут появляться в любом месте оказывать влияние, которое распространяется (независимо от области видимости) до конца исходного файла программы.
Заметьте, что определения const и inline дают альтернативы для большинства использований #define.

Замена идентификаторов

Командная строка компилятора имеет вид

#define идент строка_символов


вызывает замену препроцессором последующих вхождений идентификатора, заданного строкой символов. Точка с запятой внутри (или в конце) строки символов является частью этой строки.
Строка вида

#define идент( идент , ..., идент ) строка_символов


где отсутствует пробел между первым идентификатором и (, является макроопределением с параметрами. Последующие вхождения первого идентификатора с идущими за ним (, последовательностью символов, разграниченной запятыми, и ), заменяются строкой символов, заданной в определении. Каждое местоположение идентификатора, замеченного в списке параметров определения, заменяется соответствующей строкой из вызова. Фактическими параметрами вызова являются строки символов, разделенные запятыми; однако запятые в строке, заключенной в кавычки, или в круглых скобках не являются разделителями параметров. Число формальных и фактических параметров должно совпадать. Строки и символьные константы в символьной строке сканируются в поисках формальных параметров, но строки и символьные константы в остальной программе не сканируются в поисках определенных (с помощью define) идентификаторов.
В обоих случаях строка замещения еще раз сканируется в поисках других определенных идентификаторов. В обоих случаях длинное определение может быть продолжено на другой строке с помощью записи \ в конце продолжаемой строки.
Командная строка вида

#undef идент


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

Включение файлов

Командная строка компилятора вида

#include "имя_файла"


вызывает замену этой строки полным содержимым файла имя_файла. Сначала именованный файл ищется в директории первоначального исходного файла, а затем в стандартных или заданных местах.
Альтернативный вариант, командная строка вида

#include <имя_файла>


производит поиск только в стандартном или заданном месте, и не ищет в директории первоначального исходного файла. (То, как эти места задаются, не является частью языка.)
Включения с помощью #include могут быть вложенными.

Условная компиляция

Командная строка компилятора вида

#if выражение


проверяет, является ли результатом вычисления выражения не-ноль. Выражение должно быть константным выражением, которые обсуждаются в #15; применительно к использованию данной директивы есть дополнительные ограничения: константное выражение не может содержать sizeof или перечислимые константы. Кроме обычных операций C может использоваться унарная операция defined. В случае применения к идентификатору она дает значение не-ноль, если этот идентификатор был ранее определен с помощью #define и после этого не было отмены определения с помощью #undef; иначе ее значение 0.
Командная строка вида

#ifdef идент


проверяет, определен ли идентификатор в препроцессоре в данный момент; то есть, был ли он объектом командной строки #define.
Командная строка вида

#ifndef идент


проверяет, является ли идентификатор неопределенным в препроцессоре в данный момент.
После строки каждого из трех видов может стоять произвольное количество строк, возможно, содержащих командную строку

#else


и далее до командной строки

#endif


Если проверенное условие истинно, то все строки между #else и #endif игнорируются. Если проверенное условие ложно, то все строки между проверкой и #else или, в случае отсутствия #else, #endif, игнорируются.
Эти конструкции могут быть вложенными.

Управление строкой

Для помощи другим препроцессорам, генерирующим программы на C, строка вида

#line константа "имя_файла"


заставляет компилятор считать, например, в целях диагностики ошибок, что константа задает номер следующей строки исходного файла, и текущий входной файл именуется идентификатором. Если идентификатор отсутствует, то запомненное имя файла не изменяется.

Неявные Описания

См. #8.1.

Обзор Типов

В этом разделе кратко собрано описание действий, которые могут совершаться над объектами различных типов.

Классы

Классовые объекты могут присваиваться, передаваться функциям как параметры и возвращаться функциями. Другие возможные операции, как, например, проверка равенства, могут быть определены пользователем; см. #8.5.10.

Функции

Есть только две вещи, которые можно проделывать с функцией: вызывать ее и брать ее адрес. Если в выражении имя функции возникает не в положении имени функции в вызове, то генерируется указатель на функцию. Так, для передачи одной функции другой можно написать

typedef int (*PF) ();

extern g (PF);

extern f ();

...

g (f);


Тогда определение g может иметь следующий вид:

g (PF funcp)

{

...

(*funcp) ();

...

}


Заметьте, что f должна быть описана явно в вызывающей программе, поскольку ее появление в g(f) не сопровождалось (.

Наши рекомендации