Командные строки препроцессора используются для условной компиляции различных частей исходного текста в зависимости от внешних условий.
#if константное_выражениеПример:
#if ABC + 3Истина, если константное выражение ABC + 3 не равно нулю.
#ifdef идентификаторПример:
#ifdef ABCистина, если идентификатор ABC определен ранее командой #define.
#ifndef идентификаторПример:
#ifndef ABCистина, если идентификатор ABC не определен в настоящий момент.
#else...#endifЕсли предшествующие проверки #if, #ifdef или #ifndef дают значение "Истина", то строки от #else до #endif игнорируются при компиляции.
Если эти проверки дают значение "Ложь", то строчки от проверки до #else (а при отсутствии #else - до #endif) игнорируются.
Команда #endif обозначает конец условной компиляции.
Пример:
#ifdef DEBUGfprintf (stderr, "location: x = %d\n", x);#endifВспомогательные директивы
Номер строки и имя файла
#line целая_константа "имя_файла"Пример:
#line 20 "ABC"Препроцессор изменяет номер текущей строки и имя компилируемого файла. Имя файла может быть опущено.
|
|
Одна из целей использования условной компиляции - сделать программу более мобильной. Изменяя несколько ключевых определений в начале файла, мы можем устанавливать различные значения и включать различные файлы для разных систем.
Пример:
#define N 3/*определение константы */void main(){#line 55 "file.c"double x[3*N];}Реакция на ошибки
#error последовательность лексемОбработка директивы приводит к выдаче диагностического сообщения в виде, определенном последовательностью лексем. Применение этой директивы совместно с условными препроцессорными командами.
Пример:
#define NAME 15В дальнейшем можно проверить ее значение и выдать сообщение, если у NAME окажется другое значение:
#if (NAME!=15)#error NAME должно быть равно 15!Сообщение будет выглядеть так:
error <имя_файла><номер_строки >; error directive: NAME должно быть равно 15!Пустая директива
#Использование этой директивы не вызывает никаких действий.
Прагмы
#pragmaЭта директива определяет действия, зависящие от конкретной реализации компилятора. Например в некоторые компиляторы входит вариант этой директивы для извещения компилятора о наличии в тексте программы команд на языке Ассемблер. Возможности команды #pragma могут быть разнообазными. Стандарта для них не существует. Если конкретный препроцессор встречает прагму, которая ему неизвестна, он ее просто игнорирует как пустую директиву. В некоторых реализациях включена прагма.
#pragma pack(n), где n= 1, 2, 4. Прагма pack позволяет влиять на упаковку смежных элементов в структурах и объединениях (см. лекцию 14).
Соглашение может быть таким:
pack(1) - выравнивание элементов по границам байтов;
pack(2) - выравнивание элементов по границам слов;
pack(4) - выравнивание элементов по границам двойных слов;
В некоторые компиляторы включены прагмы, позволяющие изменять способ передачи параметров функциям, порядок помещения параметров в стек и т.д.