Шрифт:
Для обработки наборов символов, не соответствующих ASCII, используются следующие трехсимвольные последовательности (триграммы), которые распоз-наются и обрабатываются специальным образом там, где они находятся в про-грамме (а также внутри символьных строк). Триграмма Значение ??= # ??( [ ??) ] ??< { ??> } ??/ \ ??’ ^ ??! | ??- ~ Директивы препроцессора
Все директивы препроцессора начинаются с символа #, когорый должен быть первым символом в строке, отличным от пробела. После # могут следовать один или несколько символов «пробел» или tab. Директива #define Формат 1 #define имя текст
Определяется имя идентификатора для препроцессора, это имя связывается с текстом, который начинается после первого пробела, следующего за именем, и заканчивается концом строки. При последующем использовании имени в программе оно заменяется текстом. Формат 2 #define имя (парам_ 1, парам_2,..., парам_п) текст
Определяется макрос имя, принимающий аргументы парам1, парам_2, ..., парамп, каждый из которых является идентификатором. При последующем ис-пользовании имени в программе со списком аргументов происходит подстановка текста, причем аргументы вызова этого макроса заменяют все экземпляры соответствующих параметров внутри текста.
Если макрос принимает переменное число параметров, то в конце списка аргументов используются три точки. Остальные аргументы в списке обозначаются специальным идентификатором VA_ARGS. Например, ниже определяется макрос с именем myPrintf, принимающий переменное число аргументов. #define myPrintf(...) printf ("DEBUG:" _VA_ARGSJ;
Этот макрос можно использовать, например, в форме myPrintf ("Hello world!\n"); или myPrintf ("i = %i, j = %i\n", i, j);
Если для определения требуется более чем одна строка, то для продолжения каждой строки ее нужно заканчивать символом обратного слеша. После опре-деления имени его можно использовать в любом месте данного файла.
В директивах «define, которые принимают аргументы, можно использовать оператор #, после которого следует имя аргумента. Препроцессор помещает в кавычки фактическое значение, передаваемое макросу при его вызове, то есть значение превращается в символьную строку. Например, определение #define printint(x) printf (# х "= %d\n", х)
при вызове printint (count);
раскрывается препроцессором как printf ("count" "= %i\n", count); или эквивалентно как printf ("count = %i\n", count);
Препроцессор помещает символ \ перед любой кавычкой или символами \ при выполнении этой операции преобразования в строку. Например, в случае определения #define str(x) # х вызов sir (The string ,r\t"contains a tab)
раскрывается следующим образом "The string \"\\t\"contains a tab"
В директивах «define, принимающих аргументы, допускается также оператор ##. Перед ним (или после него) ставится имя аргумента для макроса. Препроцессор берет значение, передаваемое при вызове макроса, и создает один маркер из этого аргумента и из маркера, который следует за ## (или предшествует ##). Например, в случае определения макроса #define printx(n) print! ("%i\n", x «# n );
вызов printx (5)
дает printf ("%i\n", x5);
Определение #define printx(n) printf ("x"« n "= %i\n", x ## n );
при вызове printx(1O)
дает printf ("xIO = %i\n", xIO);
после подстановки и конкатенации символьных строк.
Вокруг операторов « и #« можно не ставить пробелы. Директива #error Общий формат #error текст ...
Указанный текст записывается препроцессором как сообщение об ошибке. Директива #if Формат 1 #if константное^выражение «endif
Вычисляется константное выражение. Если результат не равен нулю, то обрабаты-ваются все строки программы до директивы «endif; в противном случае они ав-томатически пропускаются и не обрабатываются препроцессором или компи-лятором. Формат 2 #if константное_выражение_1 ... #elif константное_выражение_2 ... #elif константноевыражениеп ... #else ... #endif
Если константное выражение^ не равно нулю, то обрабатываются все строки программы до #elif, а остальные строки до «endif пропускаются. В противном случае, если константное_выражение_2не равно нулю, то обрабатываются все строки программы до следующей директивы #elif, а остальные строки до «endif про-пускаются. Если все константные выражения равны нулю, то обрабатываются строки после «else (если включена эта директива).
Как часть константного выражения можно использовать специальный оператор defined. Например, при использовании #if defined (DEBUG) ... #endif
будет обрабатываться код между «if и «endif, если ранее был определен иденти-фикатор DEBUG (см. также «ifdef в следующем разделе). Идентификатор не обя-зательно заключать в круглые скобки, то есть #if defined DEBUG
действует точно так же. Директива #ifdef
Общий формат #ifdef идентификатор ... #endif