Википедия

Препроцессор Си

Препроцессор C/C++ (англ. pre processor, предобработчик) — программа, подготавливающая код программы на языке C/C++ к компиляции.

Основные функции препроцессора

Препроцессором выполняются следующие действия:

  • замена соответствующих диграфов и триграфов на эквивалентные символы «#» и «\»;
  • удаление экранированных символов перевода строки;
  • замена строчных и блочных комментариев пустыми строками (с удалением окружающих пробелов и символов табуляции);
  • вставка (включение) содержимого произвольного файла (#include);
  • макроподстановки (#define);
  • условная компиляция (#if, #ifdef, #elif, #else, #endif);
  • вывод сообщений (#warning, #error).

Условная компиляция позволяет выбрать код для компиляции в зависимости от:

  • модели процессора (платформы);
  • разрядности адресов;
  • размерности типов;
  • наличия/отсутствия поддержки расширений языка;
  • наличия/отсутствия библиотек и/или функций;
  • особенностей поведения конкретных функций;
  • и другого.

Этапы работы препроцессора:

Язык препроцессора C/C++ не является полным по Тьюрингу.

Синтаксис директив

Директивой (командной строкой) препроцессора называется строка в исходном коде, имеющая следующий формат: #ключевое_слово параметры:

  • символ #;
  • ноль или более символов пробелов и/или табуляции;
  • одно из предопределённых ключевых слов;
  • параметры, зависимые от ключевого слова.

Список ключевых слов:

  • define — создание константы или макроса;
  • undef — удаление константы или макроса;
  • include — вставка содержимого указанного файла;
  • if — проверка истинности выражения;
  • ifdef — проверка существования константы или макроса;
  • ifndef — проверка несуществования константы или макроса;
  • else — ветка условной компиляции при ложности выражения if;
  • elif — проверка истинности другого выражения; краткая форма записи для комбинации else и if;
  • endif — конец ветки условной компиляции;
  • line — указание имени файла и номера текущей строки для компилятора;
  • error — вывод сообщения и остановка компиляции;
  • warning — вывод сообщения без остановки компиляции;
  • pragma — указание действия, зависящего от реализации, для препроцессора или компилятора;
  • если ключевое слово не указано, директива игнорируется;
  • если указано несуществующее ключевое слово, выводится сообщение об ошибке и компиляция прерывается. (В некоторых компиляторах, таких как g++, компиляция продолжается, просто показывая предупреждение.)

Описание директив

Вставка файлов (#include)

При обнаружении директив #include "..." и #include <...>, где «…» — имя файла, препроцессор читает содержимое указанного файла, выполняет директивы и замены (подстановки), заменяет директиву #include на директиву #line и обработанное содержимое файла.

Для #include "..." поиск файла выполняется в текущей папке и папках, указанных в командной строке компилятора. Для #include <...> поиск файла выполняется в папках, содержащих файлы стандартной библиотеки (пути к этим папкам зависят от реализации компилятора).

При обнаружении директивы #include последовательность-лексем , не совпадающей ни с одной из предыдущих форм, рассматривает последовательность лексем как текст, который в результате всех макроподстановок должен дать #include <...> или #include "...". Сгенерированная таким образом директива далее будет интерпретироваться в соответствии с полученной формой.

Включаемые файлы обычно содержат:

  • объявления функций;
  • объявления глобальных переменных;
  • определения интерфейсов;
  • определения типов данных;
  • и другое.

Директива #include обычно указывается в начале файла (в заголовке), поэтому включаемые файлы называются заголовочными.

Пример включения файлов из стандартной библиотеки языка C.

#include <math.h> // включение объявлений математических функций #include <stdio.h> // включение объявлений функций ввода-вывода 

Использование препроцессора считается неэффективным по следующим причинам:

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

Начиная с 1970-х годов стали появляться способы, заменившие включение файлов. В языках Java и Common Lisp используются пакеты (ключевое слово package) (см. package в Java), в языке Паскаль — англ. units (ключевые слова unit и uses), в языках Modula, OCaml, Haskell и Python — модули. В языке D, разработанном для замены языков C и C++, используется ключевые слова module и import.

Константы и макросы #define

Константы и макросы препроцессора используются для определения небольших фрагментов кода.

// константа #define BUFFER_SIZE 1024 // макрос #define NUMBER_OF_ARRAY_ITEMS( array ) ( sizeof( array ) / sizeof( *(array) ) ) 

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

Пример. Определение макроса max, принимающего два аргумента: a и b.

#define max( a, b ) ( (a) > (b) ? (a) : (b) ) 

Макрос вызывается так же, как и любая функция.

z = max( x, y ); 

После замены макроса код будет выглядеть следующим образом:

z = ( (x) > (y) ? (x) : (y) ); 

Однако, наряду с преимуществами использования макросов в языке Си, например, для определения обобщённых типов данных или отладочных инструментов, они также несколько снижают эффективность их применения и даже могут привести к ошибкам.

Например, если f и g — две функции, вызов

z = max( f(), g() ); 

не вычислит один раз f()и один раз g(), и поместит наибольшее значение в z, как этого можно было ожидать. Вместо этого одна из функций будет вычислена дважды. Если функция имеет побочные эффекты, то вероятно, что её поведение будет отличаться от ожидаемого.

Макросы Си могут походить на функции, создавая новый синтаксис в некоторых пределах, а также могут быть дополнены произвольным текстом (хотя компилятор Си требует, чтобы текст был без ошибок написанным Си-кодом или оформлен как комментарий), но у них есть некоторые ограничения как у программных конструкций. Макросы, схожие с функциями, например, могут быть вызваны как «настоящие» функции, но макрос не может быть передан другой функции при помощи указателя, по той причине, что макрос сам по себе не имеет адреса.

Некоторые современные языки обычно не используют такой способ метапрограммирования с использованием макросов как дополнений строк символов, в расчете или на автоматическое, или на ручное подключение функций и методов, а вместо этого - другие способы абстракции, такие как шаблоны, обобщённые функции или параметрический полиморфизм. В частности, [англ.] позволяют избежать одного из главных недостатков макросов в современных версиях Си и C++, так как то, что встроенная функция обеспечивает преимущество макросов в снижении накладных расходов при вызове функции, но её адрес можно передавать в указателе для косвенных вызовов или использовать в качестве параметра. Аналогично, проблема множественных вычислений, упомянутая выше в макросе max, для встроенных функций неактуальна.

Константы #define можно заменить на enum, а макросы — на функции inline.

Операторы # и ##

Эти операторы используются при создании макросов. Оператор # обрамляет параметр макроса в двойные кавычки, например:

#define make_str( bar ) # bar printf( make_str( 42 ) ); 

препроцессор преобразует в:

printf( "42" ); 

Оператор ## в макросах объединяет две лексемы, например:

#define MakePosition( x ) x##X, x##Y, x##Width, x##Height int MakePosition( Object ); 

препроцессор преобразует в:

int ObjectX, ObjectY, ObjectWidth, ObjectHeight; 

Формальное описание макроподстановок

1) Управляющая строка следующего вида заставляет препроцессор заменять идентификатор на последовательность лексем везде далее по тексту программы:

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

При этом символы пустого пространства в начале и в конце последовательности лексем выбрасываются. Повторная строка #define с тем же идентификатором считается ошибкой, если последовательности лексем не идентичны (несовпадения в символах пустого пространства не играют роли).

2) Строка следующего вида, где между первым идентификатором и открывающей круглой скобкой не должно быть символов пустого пространства, представляет собой макроопределение с параметрами, задаваемыми списком-идентификаторов.

#define идентификатор( список_идентификаторов ) последовательность_лексем 

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

Управляющая строка следующего вида приказывает препроцессору «забыть» определение, данное идентификатору:

#undef идентификатор 

Применение директивы #undef к не определенному ранее идентификатору не считается ошибкой.

{

  • Если макроопределение было задано во второй форме, то любая следующая далее в тексте программы цепочка символов, состоящая из идентификатора макроса (возможно, с последующими символами пустого пространства), открывающей скобки, списка лексем, разделенных запятыми, и закрывающей скобки, представляет собой вызов макроса.
  • Аргументами вызова макроса являются лексемы, разделенные запятыми, причем запятые, взятые в кавычки или вложенные круглые скобки, в разделении аргументов не участвуют.
  • (!)Во время группировки аргументов раскрытие макросов в них не выполняется.
  • Количество аргументов в вызове макроса должно соответствовать количеству параметров макроопределения.
  • После выделения аргументов из текста символы пустого пространства, окружающие их, отбрасываются.
  • Затем в замещающей последовательности лексем макроса каждый идентификатор-параметр, не взятый в кавычки, заменяется на соответствующий ему фактический аргумент из текста.
  • (!)Если в замещающей последовательности перед параметром не стоит знак #, если и ни перед ним, ни после него нет знака ##, то лексемы аргумента проверяются на наличие в них макровызовов; если таковые есть, то до подстановки аргумента в нём выполняется раскрытие соответствующих макросов.

На процесс подстановки влияют два специальных знака операций.

  • Во-первых, если перед параметром в замещающей строке лексем вплотную стоит знак #, то вокруг соответствующего аргумента ставятся строковые кавычки ("), а потом идентификатор параметра вместе со знаком # заменяется получившимся строковым литералом.
    • Перед каждым символом " или \, встречающимся вокруг или внутри строковой или символьной константы, автоматически вставляется обратная косая черта.
  • Во-вторых, если последовательность лексем в макроопределении любого вида содержит знак ##, то сразу после подстановки параметров он вместе с окружающими его символами пустого пространства отбрасывается, благодаря чему сцепляются соседние лексемы, образуя тем самым новую лексему.
    • Результат не определён при генерировании таким образом недопустимых лексем языка или в случае, когда получающийся текст зависит от порядка применения операции ##.
    • Кроме того, знак ## не может стоять ни в начале, ни в конце замещающей последовательности лексем.

}

  • (!)В макросах обоих видов замещающая последовательность лексем повторно просматривается в поиске новых define-идентификаторов.
  • (!)Однако если какой-либо идентификатор уже был заменен в текущем процессе раскрытия, повторное появление такого идентификатора не вызовет его замены; он останется нетронутым.
  • (!)Даже если развернутая строка макровызова начинается со знака #, она не будет воспринята как директива препроцессора.

Восклицательным знаком (!) отмечены правила, отвечающие за рекурсивные вызов и определения.

Пример раскрытия макроопределения

#define cat( x, y ) х ## у 

Вызов макроса «cat(var, 123)» будет заменён на «var123». Однако вызов «cat(cat(1, 2), 3)» не даст желаемого результата. Рассмотрим шаги работы препроцессора:

0: cat( cat( 1, 2 ), 3 ) 1: cat( 1, 2 ) ## 3 2: cat( 1, 2 )3 

Операция «##» помешала правильному раскрытию аргументов второго вызова «cat». В результате получилась следующая цепочка лексем:

cat ( 1 , 2 )3 

где «)3» — результат сцепления последней лексемы первого аргумента с первой лексемой второго аргумента, не является допустимой лексемой.

Можно задать второй уровень макроопределения в таком виде:

#define xcat( x, y ) cat( x, y ) 

Вызов «xcat(xcat(1, 2), 3)» будет заменён на «123». Рассмотрим шаги работы препроцессора:

0: xcat( xcat( 1, 2 ), 3 ) 1: сat( xcat( 1, 2 ), 3 ) 2: cat( cat( 1, 2 ), 3 ) 3: cat( 1 ## 2, 3 ) 4: cat( 12, 3 ) 5: 12 ## 3 6: 123 

Всё прошло благополучно, потому что в раскрытии макроса «xcat» не участвовал оператор «##».

Многие статические анализаторы не умеют правильно обрабатывать макросы, поэтому качество статического анализа снижается[источник не указан 3289 дней].

Предопределённые константы #define

Константы, создаваемые препроцессором автоматически:

  • __LINE__ заменяется на номер текущей строки; номер текущей строки может быть переопределен директивой #line; используется для отладки;
  • __FILE__ заменяется на имя файла; имя файла тоже может быть переопределено с помощью директивы #line;
  • __FUNCTION__ заменяется на имя текущей функции;
  • __DATE__ заменяется на текущую дату (на момент обработки кода препроцессором);
  • __TIME__ заменяется на текущее время (на момент обработки кода препроцессором);
  • __TIMESTAMP__ заменяется на текущие дату и время (на момент обработки кода препроцессором);
  • __COUNTER__ заменяется на уникальное число, начиная от 0; после каждой замены число увеличивается на единицу;
  • __STDC__ заменяется на 1, если компиляция происходит в соответствии со стандартом языка C;
  • __STDC_HOSTED__ определена в C99 и выше; заменяется на 1, если выполнение происходит под управлением ОС;
  • __STDC_VERSION__ определена в C99 и выше; для C99 заменяется на число 199901, а для C11 — на число 201112;
  • __STDC_IEC_559__ определена в C99 и выше; константа существует, если компилятор поддерживает операции с числами с плавающей точкой по стандарту IEC 60559;
  • __STDC_IEC_559_COMPLEX__ определена в C99 и выше; константа существует, если компилятор поддерживает операции с комплексными числами по стандарту IEC 60559; стандарт C99 обязывает поддерживать операции с комплексными числами;
  • __STDC_NO_COMPLEX__ определена в C11; заменяется на 1, если не поддерживаются операции с комплексными числами;
  • __STDC_NO_VLA__ определена в C11; заменяется на 1, если не поддерживаются массивы переменной длины; в С99 массивы переменной длины обязательно должны поддерживаться;
  • __VA_ARGS__ определена в C99 и позволяет создавать макросы с переменным числом аргументов.

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

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

В общем случае, программисту необходимо использовать конструкцию типа:

# ifndef FOO_H # define FOO_H ...(код заголовочного файла)... # endif 

Такая «защита макросов» предотвращает двойное подключение заголовочного файла путём проверки существования этого макроса, который имеет то же самое имя, что и заголовочный файл. Определение макроса FOO_H происходит, когда заголовочный файл впервые обрабатывается препроцессором. Затем, если этот заголовочный файл вновь подключается, FOO_H уже определен, в результате чего препроцессор пропускает полностью текст этого заголовочного файла.

То же самое можно сделать, включив в заголовочный файл директиву:

# pragma once 

Условия препроцессора можно задавать несколькими способами, например:

# ifdef x ... # else ... # endif 

или

# if x ... # else ... # endif 

Этот способ часто используется в системных заголовочных файлах для проверки различных возможностей, определение которых может меняться в зависимости от платформы; например, библиотека Glibc использует макросы с проверкой особенностей с целью проверить, что операционная система и оборудование их (макросы) корректно поддерживает при неизменности программного интерфейса.

Большинство современных языков программирования не использует такие возможности, больше полагаясь на традиционные операторы условия if...then...else..., оставляя компилятору задачу извлечения бесполезного кода из компилируемой программы.

Диграфы и триграфы

См. диграфы и триграфы в языках C/C++.

Препроцессор обрабатывает диграфы «%:» («#»), «%:%:» («##») и триграфы «??=» («#»), «??/» («\»).

Препроцессор считает последовательность «%:%:» двумя токенами при обработке кода C и одним токеном при обработке кода C++.

См. также

  • Макропроцессор m4
  • [англ.]

Примечания

Ссылки

  • Документация к препроцессору GCC Архивная копия от 26 марта 2011 на Wayback Machine (англ.)

Википедия, чтение, книга, библиотека, поиск, нажмите, истории, книги, статьи, wikipedia, учить, информация, история, скачать, скачать бесплатно, mp3, видео, mp4, 3gp, jpg, jpeg, gif, png, картинка, музыка, песня, фильм, игра, игры, мобильный, телефон, Android, iOS, apple, мобильный телефон, Samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Сеть, компьютер, Информация о Препроцессор Си, Что такое Препроцессор Си? Что означает Препроцессор Си?

V etoj state slishkom korotkaya preambula Pozhalujsta dopolnite vvodnuyu sekciyu kratko raskryvayushuyu temu stati i obobshayushuyu eyo soderzhimoe 29 iyunya 2021 Etu statyu neobhodimo ispravit v sootvetstvii s pravilami Vikipedii ob oformlenii statej Pozhalujsta pomogite uluchshit etu statyu 29 iyunya 2021 Preprocessor C C angl pre processor predobrabotchik programma podgotavlivayushaya kod programmy na yazyke C C k kompilyacii Osnovnye funkcii preprocessoraPreprocessorom vypolnyayutsya sleduyushie dejstviya zamena sootvetstvuyushih digrafov i trigrafov na ekvivalentnye simvoly i udalenie ekranirovannyh simvolov perevoda stroki zamena strochnyh i blochnyh kommentariev pustymi strokami s udaleniem okruzhayushih probelov i simvolov tabulyacii vstavka vklyuchenie soderzhimogo proizvolnogo fajla include makropodstanovki define uslovnaya kompilyaciya if ifdef elif else endif vyvod soobshenij warning error Uslovnaya kompilyaciya pozvolyaet vybrat kod dlya kompilyacii v zavisimosti ot modeli processora platformy razryadnosti adresov razmernosti tipov nalichiya otsutstviya podderzhki rasshirenij yazyka nalichiya otsutstviya bibliotek i ili funkcij osobennostej povedeniya konkretnyh funkcij i drugogo Etapy raboty preprocessora leksicheskij analiz koda C C sintaksicheskij analiz ne vypolnyaetsya obrabotka direktiv vypolnenie podstanovok digrafov i trigrafov kommentariev direktiv leksem zadannyh direktivami Yazyk preprocessora C C ne yavlyaetsya polnym po Tyuringu Sintaksis direktivDirektivoj komandnoj strokoj preprocessora nazyvaetsya stroka v ishodnom kode imeyushaya sleduyushij format klyuchevoe slovo parametry simvol a href wiki D0 9E D0 BA D1 82 D0 BE D1 82 D0 BE D1 80 D0 BF class mw redirect title Oktotorp a nol ili bolee simvolov probelov i ili tabulyacii odno iz predopredelyonnyh klyuchevyh slov parametry zavisimye ot klyuchevogo slova Spisok klyuchevyh slov define sozdanie konstanty ili makrosa undef udalenie konstanty ili makrosa include vstavka soderzhimogo ukazannogo fajla if proverka istinnosti vyrazheniya ifdef proverka sushestvovaniya konstanty ili makrosa ifndef proverka nesushestvovaniya konstanty ili makrosa else vetka uslovnoj kompilyacii pri lozhnosti vyrazheniya if elif proverka istinnosti drugogo vyrazheniya kratkaya forma zapisi dlya kombinacii else i if endif konec vetki uslovnoj kompilyacii line ukazanie imeni fajla i nomera tekushej stroki dlya kompilyatora error vyvod soobsheniya i ostanovka kompilyacii warning vyvod soobsheniya bez ostanovki kompilyacii pragma ukazanie dejstviya zavisyashego ot realizacii dlya preprocessora ili kompilyatora esli klyuchevoe slovo ne ukazano direktiva ignoriruetsya esli ukazano nesushestvuyushee klyuchevoe slovo vyvoditsya soobshenie ob oshibke i kompilyaciya preryvaetsya V nekotoryh kompilyatorah takih kak g kompilyaciya prodolzhaetsya prosto pokazyvaya preduprezhdenie Opisanie direktivV razdele ne hvataet ssylok na istochniki sm rekomendacii po poisku Informaciya dolzhna byt proveryaema inache ona mozhet byt udalena Vy mozhete otredaktirovat statyu dobaviv ssylki na avtoritetnye istochniki v vide snosok 3 iyulya 2016 Vstavka fajlov include Pri obnaruzhenii direktiv include i include lt gt gde imya fajla preprocessor chitaet soderzhimoe ukazannogo fajla vypolnyaet direktivy i zameny podstanovki zamenyaet direktivu include na direktivu line i obrabotannoe soderzhimoe fajla Dlya include poisk fajla vypolnyaetsya v tekushej papke i papkah ukazannyh v komandnoj stroke kompilyatora Dlya include lt gt poisk fajla vypolnyaetsya v papkah soderzhashih fajly standartnoj biblioteki puti k etim papkam zavisyat ot realizacii kompilyatora Pri obnaruzhenii direktivy include posledovatelnost leksem ne sovpadayushej ni s odnoj iz predydushih form rassmatrivaet posledovatelnost leksem kak tekst kotoryj v rezultate vseh makropodstanovok dolzhen dat include lt gt ili include Sgenerirovannaya takim obrazom direktiva dalee budet interpretirovatsya v sootvetstvii s poluchennoj formoj Vklyuchaemye fajly obychno soderzhat obyavleniya funkcij obyavleniya globalnyh peremennyh opredeleniya interfejsov opredeleniya tipov dannyh i drugoe Direktiva include obychno ukazyvaetsya v nachale fajla v zagolovke poetomu vklyuchaemye fajly nazyvayutsya zagolovochnymi Primer vklyucheniya fajlov iz standartnoj biblioteki yazyka C include lt math h gt vklyuchenie obyavlenij matematicheskih funkcij include lt stdio h gt vklyuchenie obyavlenij funkcij vvoda vyvoda Ispolzovanie preprocessora schitaetsya neeffektivnym po sleduyushim prichinam kazhdyj raz pri vklyuchenii fajlov vypolnyayutsya direktivy i zameny podstanovki kompilyator mog by sohranyat rezultaty preprocessirovaniya dlya ispolzovaniya v budushem mnozhestvennye vklyucheniya odnogo fajla prihoditsya predotvrashat vruchnuyu s pomoshyu direktiv uslovnoj kompilyacii kompilyator mog by vypolnyat etu zadachu samostoyatelno Nachinaya s 1970 h godov stali poyavlyatsya sposoby zamenivshie vklyuchenie fajlov V yazykah Java i Common Lisp ispolzuyutsya pakety klyuchevoe slovo package sm package v Java v yazyke Paskal angl units klyuchevye slova unit i uses v yazykah Modula OCaml Haskell i Python moduli V yazyke D razrabotannom dlya zameny yazykov C i C ispolzuetsya klyuchevye slova module i import Konstanty i makrosy define V razdele ne hvataet ssylok na istochniki sm rekomendacii po poisku Informaciya dolzhna byt proveryaema inache ona mozhet byt udalena Vy mozhete otredaktirovat statyu dobaviv ssylki na avtoritetnye istochniki v vide snosok 3 iyulya 2016 Konstanty i makrosy preprocessora ispolzuyutsya dlya opredeleniya nebolshih fragmentov koda konstanta define BUFFER SIZE 1024 makros define NUMBER OF ARRAY ITEMS array sizeof array sizeof array Kazhdaya konstanta i kazhdyj makros zamenyayutsya sootvetstvuyushim im opredeleniem Makrosy imeyut parametry pohozhi na funkcii ispolzuyutsya dlya umensheniya nakladnyh rashodov pri vyzove funkcij v sluchayah kogda nebolshogo koda vyzyvaemogo funkciej dostatochno dlya oshutimogo snizheniya proizvoditelnosti Primer Opredelenie makrosa max prinimayushego dva argumenta a i b define max a b a gt b a b Makros vyzyvaetsya tak zhe kak i lyubaya funkciya z max x y Posle zameny makrosa kod budet vyglyadet sleduyushim obrazom z x gt y x y Odnako naryadu s preimushestvami ispolzovaniya makrosov v yazyke Si naprimer dlya opredeleniya obobshyonnyh tipov dannyh ili otladochnyh instrumentov oni takzhe neskolko snizhayut effektivnost ih primeneniya i dazhe mogut privesti k oshibkam Naprimer esli f i g dve funkcii vyzov z max f g ne vychislit odin raz f i odin raz g i pomestit naibolshee znachenie v z kak etogo mozhno bylo ozhidat Vmesto etogo odna iz funkcij budet vychislena dvazhdy Esli funkciya imeet pobochnye effekty to veroyatno chto eyo povedenie budet otlichatsya ot ozhidaemogo Makrosy Si mogut pohodit na funkcii sozdavaya novyj sintaksis v nekotoryh predelah a takzhe mogut byt dopolneny proizvolnym tekstom hotya kompilyator Si trebuet chtoby tekst byl bez oshibok napisannym Si kodom ili oformlen kak kommentarij no u nih est nekotorye ogranicheniya kak u programmnyh konstrukcij Makrosy shozhie s funkciyami naprimer mogut byt vyzvany kak nastoyashie funkcii no makros ne mozhet byt peredan drugoj funkcii pri pomoshi ukazatelya po toj prichine chto makros sam po sebe ne imeet adresa Nekotorye sovremennye yazyki obychno ne ispolzuyut takoj sposob metaprogrammirovaniya s ispolzovaniem makrosov kak dopolnenij strok simvolov v raschete ili na avtomaticheskoe ili na ruchnoe podklyuchenie funkcij i metodov a vmesto etogo drugie sposoby abstrakcii takie kak shablony obobshyonnye funkcii ili parametricheskij polimorfizm V chastnosti angl pozvolyayut izbezhat odnogo iz glavnyh nedostatkov makrosov v sovremennyh versiyah Si i C tak kak to chto vstroennaya funkciya obespechivaet preimushestvo makrosov v snizhenii nakladnyh rashodov pri vyzove funkcii no eyo adres mozhno peredavat v ukazatele dlya kosvennyh vyzovov ili ispolzovat v kachestve parametra Analogichno problema mnozhestvennyh vychislenij upomyanutaya vyshe v makrose max dlya vstroennyh funkcij neaktualna Konstanty define mozhno zamenit na enum a makrosy na funkcii inline Operatory i Eti operatory ispolzuyutsya pri sozdanii makrosov Operator obramlyaet parametr makrosa v dvojnye kavychki naprimer define make str bar bar printf make str 42 preprocessor preobrazuet v printf 42 Operator v makrosah obedinyaet dve leksemy naprimer define MakePosition x x X x Y x Width x Height int MakePosition Object preprocessor preobrazuet v int ObjectX ObjectY ObjectWidth ObjectHeight Formalnoe opisanie makropodstanovok 1 Upravlyayushaya stroka sleduyushego vida zastavlyaet preprocessor zamenyat identifikator na posledovatelnost leksem vezde dalee po tekstu programmy define identifikator posledovatelnost leksem Pri etom simvoly pustogo prostranstva v nachale i v konce posledovatelnosti leksem vybrasyvayutsya Povtornaya stroka define s tem zhe identifikatorom schitaetsya oshibkoj esli posledovatelnosti leksem ne identichny nesovpadeniya v simvolah pustogo prostranstva ne igrayut roli 2 Stroka sleduyushego vida gde mezhdu pervym identifikatorom i otkryvayushej krugloj skobkoj ne dolzhno byt simvolov pustogo prostranstva predstavlyaet soboj makroopredelenie s parametrami zadavaemymi spiskom identifikatorov define identifikator spisok identifikatorov posledovatelnost leksem Kak i v pervoj forme simvoly pustogo prostranstva v nachale i v konce posledovatelnosti leksem vybrasyvayutsya i makros mozhet byt povtorno opredelen tolko s identichnym po kolichestvu i imenam spiskom parametrov i s toj zhe posledovatelnostyu leksem Upravlyayushaya stroka sleduyushego vida prikazyvaet preprocessoru zabyt opredelenie dannoe identifikatoru undef identifikator Primenenie direktivy undef k ne opredelennomu ranee identifikatoru ne schitaetsya oshibkoj Esli makroopredelenie bylo zadano vo vtoroj forme to lyubaya sleduyushaya dalee v tekste programmy cepochka simvolov sostoyashaya iz identifikatora makrosa vozmozhno s posleduyushimi simvolami pustogo prostranstva otkryvayushej skobki spiska leksem razdelennyh zapyatymi i zakryvayushej skobki predstavlyaet soboj vyzov makrosa Argumentami vyzova makrosa yavlyayutsya leksemy razdelennye zapyatymi prichem zapyatye vzyatye v kavychki ili vlozhennye kruglye skobki v razdelenii argumentov ne uchastvuyut Vo vremya gruppirovki argumentov raskrytie makrosov v nih ne vypolnyaetsya Kolichestvo argumentov v vyzove makrosa dolzhno sootvetstvovat kolichestvu parametrov makroopredeleniya Posle vydeleniya argumentov iz teksta simvoly pustogo prostranstva okruzhayushie ih otbrasyvayutsya Zatem v zameshayushej posledovatelnosti leksem makrosa kazhdyj identifikator parametr ne vzyatyj v kavychki zamenyaetsya na sootvetstvuyushij emu fakticheskij argument iz teksta Esli v zameshayushej posledovatelnosti pered parametrom ne stoit znak esli i ni pered nim ni posle nego net znaka to leksemy argumenta proveryayutsya na nalichie v nih makrovyzovov esli takovye est to do podstanovki argumenta v nyom vypolnyaetsya raskrytie sootvetstvuyushih makrosov Na process podstanovki vliyayut dva specialnyh znaka operacij Vo pervyh esli pered parametrom v zameshayushej stroke leksem vplotnuyu stoit znak to vokrug sootvetstvuyushego argumenta stavyatsya strokovye kavychki a potom identifikator parametra vmeste so znakom zamenyaetsya poluchivshimsya strokovym literalom Pered kazhdym simvolom ili vstrechayushimsya vokrug ili vnutri strokovoj ili simvolnoj konstanty avtomaticheski vstavlyaetsya obratnaya kosaya cherta Vo vtoryh esli posledovatelnost leksem v makroopredelenii lyubogo vida soderzhit znak to srazu posle podstanovki parametrov on vmeste s okruzhayushimi ego simvolami pustogo prostranstva otbrasyvaetsya blagodarya chemu sceplyayutsya sosednie leksemy obrazuya tem samym novuyu leksemu Rezultat ne opredelyon pri generirovanii takim obrazom nedopustimyh leksem yazyka ili v sluchae kogda poluchayushijsya tekst zavisit ot poryadka primeneniya operacii Krome togo znak ne mozhet stoyat ni v nachale ni v konce zameshayushej posledovatelnosti leksem V makrosah oboih vidov zameshayushaya posledovatelnost leksem povtorno prosmatrivaetsya v poiske novyh define identifikatorov Odnako esli kakoj libo identifikator uzhe byl zamenen v tekushem processe raskrytiya povtornoe poyavlenie takogo identifikatora ne vyzovet ego zameny on ostanetsya netronutym Dazhe esli razvernutaya stroka makrovyzova nachinaetsya so znaka ona ne budet vosprinyata kak direktiva preprocessora Vosklicatelnym znakom otmecheny pravila otvechayushie za rekursivnye vyzov i opredeleniya Primer raskrytiya makroopredeleniya define cat x y h u Vyzov makrosa cat var 123 budet zamenyon na var123 Odnako vyzov cat cat 1 2 3 ne dast zhelaemogo rezultata Rassmotrim shagi raboty preprocessora 0 cat cat 1 2 3 1 cat 1 2 3 2 cat 1 2 3 Operaciya pomeshala pravilnomu raskrytiyu argumentov vtorogo vyzova cat V rezultate poluchilas sleduyushaya cepochka leksem cat 1 2 3 gde 3 rezultat scepleniya poslednej leksemy pervogo argumenta s pervoj leksemoj vtorogo argumenta ne yavlyaetsya dopustimoj leksemoj Mozhno zadat vtoroj uroven makroopredeleniya v takom vide define xcat x y cat x y Vyzov xcat xcat 1 2 3 budet zamenyon na 123 Rassmotrim shagi raboty preprocessora 0 xcat xcat 1 2 3 1 sat xcat 1 2 3 2 cat cat 1 2 3 3 cat 1 2 3 4 cat 12 3 5 12 3 6 123 Vsyo proshlo blagopoluchno potomu chto v raskrytii makrosa xcat ne uchastvoval operator Mnogie staticheskie analizatory ne umeyut pravilno obrabatyvat makrosy poetomu kachestvo staticheskogo analiza snizhaetsya istochnik ne ukazan 3289 dnej Predopredelyonnye konstanty define Konstanty sozdavaemye preprocessorom avtomaticheski LINE zamenyaetsya na nomer tekushej stroki nomer tekushej stroki mozhet byt pereopredelen direktivoj line ispolzuetsya dlya otladki FILE zamenyaetsya na imya fajla imya fajla tozhe mozhet byt pereopredeleno s pomoshyu direktivy line FUNCTION zamenyaetsya na imya tekushej funkcii DATE zamenyaetsya na tekushuyu datu na moment obrabotki koda preprocessorom TIME zamenyaetsya na tekushee vremya na moment obrabotki koda preprocessorom TIMESTAMP zamenyaetsya na tekushie datu i vremya na moment obrabotki koda preprocessorom COUNTER zamenyaetsya na unikalnoe chislo nachinaya ot 0 posle kazhdoj zameny chislo uvelichivaetsya na edinicu STDC zamenyaetsya na 1 esli kompilyaciya proishodit v sootvetstvii so standartom yazyka C STDC HOSTED opredelena v C99 i vyshe zamenyaetsya na 1 esli vypolnenie proishodit pod upravleniem OS STDC VERSION opredelena v C99 i vyshe dlya C99 zamenyaetsya na chislo 199901 a dlya C11 na chislo 201112 STDC IEC 559 opredelena v C99 i vyshe konstanta sushestvuet esli kompilyator podderzhivaet operacii s chislami s plavayushej tochkoj po standartu IEC 60559 STDC IEC 559 COMPLEX opredelena v C99 i vyshe konstanta sushestvuet esli kompilyator podderzhivaet operacii s kompleksnymi chislami po standartu IEC 60559 standart C99 obyazyvaet podderzhivat operacii s kompleksnymi chislami STDC NO COMPLEX opredelena v C11 zamenyaetsya na 1 esli ne podderzhivayutsya operacii s kompleksnymi chislami STDC NO VLA opredelena v C11 zamenyaetsya na 1 esli ne podderzhivayutsya massivy peremennoj dliny v S99 massivy peremennoj dliny obyazatelno dolzhny podderzhivatsya VA ARGS opredelena v C99 i pozvolyaet sozdavat makrosy s peremennym chislom argumentov Uslovnaya kompilyaciya Osnovnaya statya Include guard Preprocessor yazyka Si predostavlyaet vozmozhnost kompilyacii s usloviyami Eto dopuskaet vozmozhnost sushestvovaniya razlichnyh versij odnogo koda Obychno takoj podhod ispolzuetsya dlya nastrojki programmy pod platformu kompilyatora sostoyanie otlazhivaemyj kod mozhet byt vydelen v rezultiruyushem kode ili vozmozhnost proverki podklyucheniya fajla strogo odin raz V obshem sluchae programmistu neobhodimo ispolzovat konstrukciyu tipa ifndef FOO H define FOO H kod zagolovochnogo fajla endif Takaya zashita makrosov predotvrashaet dvojnoe podklyuchenie zagolovochnogo fajla putyom proverki sushestvovaniya etogo makrosa kotoryj imeet to zhe samoe imya chto i zagolovochnyj fajl Opredelenie makrosa FOO H proishodit kogda zagolovochnyj fajl vpervye obrabatyvaetsya preprocessorom Zatem esli etot zagolovochnyj fajl vnov podklyuchaetsya FOO H uzhe opredelen v rezultate chego preprocessor propuskaet polnostyu tekst etogo zagolovochnogo fajla To zhe samoe mozhno sdelat vklyuchiv v zagolovochnyj fajl direktivu pragma once Usloviya preprocessora mozhno zadavat neskolkimi sposobami naprimer ifdef x else endif ili if x else endif Etot sposob chasto ispolzuetsya v sistemnyh zagolovochnyh fajlah dlya proverki razlichnyh vozmozhnostej opredelenie kotoryh mozhet menyatsya v zavisimosti ot platformy naprimer biblioteka Glibc ispolzuet makrosy s proverkoj osobennostej s celyu proverit chto operacionnaya sistema i oborudovanie ih makrosy korrektno podderzhivaet pri neizmennosti programmnogo interfejsa Bolshinstvo sovremennyh yazykov programmirovaniya ne ispolzuet takie vozmozhnosti bolshe polagayas na tradicionnye operatory usloviya if then else ostavlyaya kompilyatoru zadachu izvlecheniya bespoleznogo koda iz kompiliruemoj programmy Digrafy i trigrafyV razdele ne hvataet ssylok na istochniki sm rekomendacii po poisku Informaciya dolzhna byt proveryaema inache ona mozhet byt udalena Vy mozhete otredaktirovat statyu dobaviv ssylki na avtoritetnye istochniki v vide snosok 3 iyulya 2016 Sm digrafy i trigrafy v yazykah C C Preprocessor obrabatyvaet digrafy i trigrafy Preprocessor schitaet posledovatelnost dvumya tokenami pri obrabotke koda C i odnim tokenom pri obrabotke koda C Sm takzheMakroprocessor m4 angl PrimechaniyaSsylkiDokumentaciya k preprocessoru GCC Arhivnaya kopiya ot 26 marta 2011 na Wayback Machine angl Dlya uluchsheniya etoj stati po informacionnym tehnologiyam zhelatelno Najti i oformit v vide snosok ssylki na nezavisimye avtoritetnye istochniki podtverzhdayushie napisannoe Pozhalujsta posle ispravleniya problemy isklyuchite eyo iz spiska parametrov Posle ustraneniya vseh nedostatkov etot shablon mozhet byt udalyon lyubym uchastnikom

NiNa.Az

NiNa.Az - Абсолютно бесплатная система, которая делится для вас информацией и контентом 24 часа в сутки.
Взгляните
Закрыто