Когда препроцессор обрабатывает директиву #ifdef, он проверяет, определен ли в данный момент < идентификатор > директивой #define. Если да, условие считается истинным, если нет — ложным.
Директива #ifndefпротивоположна по действию директиве #ifdef. Если < идентификатор > не был определен директивой #define, или его определение уже отменено директивой #undef, то условие считается истинным. В противном случае условие ложно.
Управление нумерацией строк
Синтаксис:
#line < константа > ["имя-файла"]
Директива #lineсообщает компилятору языка Си об изменении имени исходного файла и порядка нумерации строк. Это изменение отражается только на диагностических сообщениях компилятора: исходный файл будет теперь именоваться как < имя-файла >, а текущая компилируемая строка получит номер < константа >. После обработки очередной строки счетчик номеров строк увеличивается на единицу. В случае изменения номера строки и имени исходного файла директивой #lineкомпилятор "забывает" их прежние значения и продолжает работу уже с новыми значениями.
Директива #lineобычно используется автоматическими генераторами программ для того, чтобы диагностические сообщения относились не к исходному файлу, а к сгенерированной программе.
< Константа > в директиве #lineможет быть произвольной целой константой. < Имя-файла > может быть произвольной комбинацией символов, заключенной в двойные кавычки. Если имя файла опущено, то имя исходного файла остается прежним.
Текущий номер строки и имя исходного файла доступны в программе через псевдопеременные с именами __LINE__ и __FILE__. Эти псевдопеременные могут быть использованы для выдачи во время выполнения сообщений о точном местоположении ошибки.
Значением псевдопеременной __FILE__ является строка, представляющая имя файла, заключенное в двойные кавычки. Поэтому для печати имени исходного файла не требуется заключать сам идентификатор __FILE__ в двойные кавычки.
Примеры.
/* пример 1 */
#line 151 "copy.с"
/* пример 2 */
#define ASSERT(cond) if (!cond)\
{printf ("ошибка в строке %d файла %s\n", \
__LINE__, __FILE__);} else;
В первом примере устанавливается имя исходного файла сору.с и текущий номер строки 151.
Во втором примере в макроопределении ASSERT используются псевдопеременные __LINE__ и __FILE__ для печати сообщения об ошибке, содержащего координаты исходного файла, если некоторое условие, заданное макроаргументом cond, ложно.
Директива обработки ошибок
В СП ТС реализована директива #error. Ее формат:
#error < текст >
Обычно эту директиву записывают среди директив условной компиляции для обнаружения некоторой недопустимой ситуации. По директиве #errorпрепроцессор прерывает компиляцию и выдает следующее сообщение:
Fatal: < имя-файла > < номер-строки > Error directive: < текст >
Fatal — признак фатальной ошибки; < имя-файла > — имя исходного файла; < номер-строки > — текущий номер строки; Error directive — сообщение об ошибке в директиве; < текст > — собственно текст диагностического сообщения.
Например, если именованная константа MYVAL может иметь значение либо 0, либо 1, можно поместить в исходный файл операторы условной компиляции для проверки на некорректное значение MYVAL:
#if (MYVAL != 0 && MYVAL != 1)
#error MYVAL должно иметь значение либо 0, либо 1
#endif
Препроцессор просматривает текст сообщения в директиве #error, и исключает из него комментарии (если они имеются), но именованные константы и макроопределения в тексте не выявляет и макроподстановку не производит.
Для повышения читабельности программ СП ТС распознает пустую директиву, состоящую из строки, содержащей просто знак #. Эта директива всегда игнорируется.
Указания компилятору языка Си
Синтаксис:
#pragma < последовательность-символов >
Указания компилятору, или прагмы, предназначены для исполнения компилятором в процессе его работы. < Последовательность-символов > задает определенную инструкцию компилятору и, возможно, аргументы.
Набор прагм для каждого компилятора языка Си различен. Для получения подробной информации о прагмах смотрите системную документацию по используемому вами компилятору.
Читать дальше