Отличными примерами расширения языка при помощи макросов может служить их использование в семействе языков программирования Лисп. В то время как эти языки сами по себе имеют простые ядра, ориентированные на динамические типы, стандартные поставки Схема, императивы Common Lisp, объектно-ориентированное программирование ориентированы на статические типы. Почти все эти свойства реализованы синтаксическими препроцессорами, хотя это несет в себе отпечаток этапа компиляции «расширения макросами», управляемой компилятором Лисп. Это все еще может считаться формой препроцессорной обработки, так как это происходит перед остальными этапами компиляции.
Аналогично, типобезопасные регулярные выражения или генерация кода могут быть добавлены в синтаксис и семантику сопрограммы или волокна), монады или прозрачная обработка XML.
Одной из необычных особенностей семейства языков Лисп является возможность использования макросов для создания встроенного предметно-ориентированного языка программирования.
Препроцессор/язык MetaOCaml обеспечивает схожие возможности и для внешнего предметно-ориентированного языка программирования. Этот препроцессор получая описание семантики языка (т. н. интерпретация) и комбинируя интерпретацию во время компиляции и генерации кода, передает это определение компилятору языка
Препроцессоры, выполняя только один из этапов трансляции, ориентированы на задачу фрагментарной обработки данных (например, компиляция языка Си).
Сходные с ними программы, называемые в таком случае макропроцессорами, также могут предназначаться для общих целей, то есть перед ними не ставится цель реализации специфического использования или языка программирования, а они разрабатываются для использования широкого круга задач обработки данных.Макропроцессор m4 вероятно наиболее известный пример подобного макропроцесора общего назначения.
#define
и
#include
для создания эффективной разметки при работе grompp.
Посмотрите «preprocessor» в Викисловаре, свободном словаре.
ВикиЧтение
C++
Хилл Мюррей
Содержание
11.3 Условная Компиляция
Командная строка компилятора вида
#if выражение
проверяет, является ли результатом вычисления выражения не-ноль. Выражение должно быть константным выражением, котрые обсуждаются в #12. Кроме обычных операций С++ может ипользоваться унарная операция defined. При применении к идетификатору она дает значение не-ноль, если этот идентификатор был ранее определен с помощью #define и после этого не было отмены определения с помощью #undef; иначе ее значение 0. Командная строка вида
#ifdef идентификатор
проверяет, определен ли идентификатор в препроцессоре в данный момент; то есть, был ли он объектом командной строки # define. Командная строка вида
#ifndef идентификатор
проверяет, является ли идентификатор неопределенным в препроцессоре в данный момент.
После каждого из трех видов может стоять произвольное количество строк, возможно, содержащих командную строку
#else
и далее до командной строки
#endif
Если проверенное условие истинно, то все строки между #else и #endif игнорируются. Если проверенное условие ложно, то все строки между проверкой и #else или, в случае отсуттвия #else, #endif, игнорируются.
Эти конструкции могут быть вложенными.
15.2. Компиляция для отладки Для использования отладчика исходного кода, отлаживаемый исполняемый файл должен быть откомпилирован с опцией компилятора -g. Эта опция заставляет компилятор внедрять в объектный код дополнительные отладочные идентификаторы; то есть
Условная переменная Одним из важнейших принципов использования мьютексов является максимальное сокращение размеров критической секции, то есть участка, который потоки должны проходить последовательно. Однако зачастую возникает необходимость ожидания выполнения
Компиляция Процедура создания большинства приложений является общей и приведена на рис. 2.2. Рис. 2.2. Схема компиляции программыПервой фазой является стадия компиляции, когда файлы с исходными текстами программы, включая файлы заголовков, обрабатываются компилятором
8.5. Условная подстановка параметров Условная подстановка позволяет проверить, установлен ли определенный параметр, или использовать вместо его значения другое. Значение самого параметра при этом не изменяется. Допустимые виды условных подстановок перечислены в
28.2. Компиляция модуля Компилировать мы будем файл module.
3.4.3. Компиляция Как правило, исходные коды программ распространяются в виде архива с «двойным расширением» -.tar.gz. Исходный код принято распаковывать в каталог /usr/src. Поэтому для распаковки архива вам нужно выполнить следующие команды:sucd /usr/srcgunzip архив.tar.gztar xvf
R.16.5 Условная трансляция С помощью препроцессора можно организовать условную трансляцию программы. Синтаксически это задается следующим образом:условное: часть-if части-elif opt часть-else opt строка-endifчасть-if: строка-if текстстрока-if: # if выражение-константа # ifdef
Компиляция программ Даже после появления пакетов, которые представляли собой уже скомпилированные программы, компиляция долгое время оставалась и для некоторых остается основным средством установки. Примечание Первые прекомпилированные наборы появились в
Почему компиляция? Читатели, пользовавшиеся языком Бейсик, могут удивиться, зачем столько шагов для того, чтобы выполнить программу. Кажется, что такой способ компиляции требует больше времени (и в некоторых случаях это может быть действительно так). Но, поскольку в
Условная операция В языке Си имеется одна тернарная операция — уловная. Она имеет следующий синтаксис:<операнд1> ? <операнд2>: <операнд3>Выражение <операнд1> вычисляется и сравнивается с нулем. Выражение может иметь целый, плавающий тип, либо быть указателем.
Условная компиляция В этом разделе описываются директивы, которые управляют условной компиляцией. Эти директивы позволяют исключить из процесса компиляции какие-либо части исходного файла посредством проверки условий (константных
Условная обработка В XSLT имеются две инструкции, которые поддерживают условную обработку — xsl:if и xsl:choose. Инструкция xsl:if позволяет создавать простые условия типа «если-то», в то время как xsl:choose создает более сложную конструкцию для выбора одной из нескольких имеющихся
1.1.2 Компиляция Откуда появились выходной поток cout и код, реализующий операцию вывода ««? Для получения выполняемого кода написанная на С++ программа должна быть скомпилирована. По своей сути процесс компиляции такой же, как и для С, и в нем участвует большая часть входящих
7. 13 Условная Операция условное_выражение: выражение ? выражение : выражениеУсловная операция группирует слева направо. Вычисляется первое выражение, и если оно не 0, то результатом является значение второго выражения, в противном случае значение третьего выражения. Если
11.3 Условная Компиляция Командная строка компилятора вида#if выражениепроверяет, является ли результатом вычисления выражения не-ноль. Выражение должно быть константным выражением, котрые обсуждаются в #12. Кроме обычных операций С++ может ипользоваться унарная операция
Условная Инструкция (Conditional) Эта инструкция задает различные формы обработки в зависимости от выполнения определенных условий. Основная форма:if boolean_expression theninstruction; instruction; …elseinstruction; instruction; . ..endгде каждая ветвь может иметь произвольное число инструкций (а возможно и не
Улучшить артикул
Сохранить статью
Нравится Статья
Улучшить статью
Сохранить статью
Нравится Статья
Основы директив препроцессора C/C++ Директивы препроцессора: Почти в каждой программе, с которой мы сталкиваемся на C/C++, мы видим несколько строк в верхней части программы, которым предшествует знак решетки (#). Эти строки предварительно обрабатываются компилятором перед началом фактической компиляции. Конец этих строк обозначается символом новой строки «\n», точка с запятой «;» не требуется для завершения этих строк. Директивы препроцессора в основном используются при определении макросов, оценке условных операторов, включении исходного файла, директиве pragma, управлении строкой, обнаружении ошибок и т. д. В этом посте мы обсудим еще несколько типов директив препроцессора, приведенных ниже:
Давайте теперь подробно рассмотрим каждую из этих директив:
#ifdef МАКРОС контролируемый текст #endif /* имя макроса */
ifndef имя_макроса заявление1; заявление2; заявление3; . . . заявление N; endif
#if макрос_условие заявления #элиф макрос_условие заявления #еще заявления #endif
|
50
50
#номер строки "имя файла"
#error необязательная_ошибка
|
ошибка: #error GeeksforGeeks не найден!
Список литературы:
Эта статья представлена на 9002 9002 9002 9002 9002 9002 9002 9002 . Агарвал . Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью с помощью write. geeksforgeeks.org или отправить ее по адресу [email protected]. Посмотрите, как ваша статья появится на главной странице GeeksforGeeks, и помогите другим гикам. Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по теме, обсуждаемой выше.
Нравится Статья
Сохранить статью
Язык C++
Препроцессор
Препроцессор поддерживает условную компиляцию частей исходного файла. Это поведение контролируется #if
, #else
, #elif
, #ifdef
, #ifndef
, #elifdef
, #elifndefsince
и0103 #endif директивы.
|
#if выражение | |||||||||
#ifdef идентификатор | |||||||||
#ifndef идентификатор | |||||||||
#elif выражение | |||||||||
#elifdef идентификатор | (начиная с С++ 23) | ||||||||
#elifndef идентификатор | (начиная с С++ 23) | ||||||||
#еще | |||||||||
#endif | |||||||||
The conditional preprocessing block starts with #if
, #ifdef
or #ifndef
directive, then optionally includes any number of #elif
, #elifdef
, or #elifndef
(начиная с C++23), затем необязательно включает не более одной директивы #else
и завершается директивой #endif
. Любые внутренние условные блоки предварительной обработки обрабатываются отдельно.
Каждое из #if
, #ifdef
, #ifndef
, #elif
, #elifdef
, #elifndef
4 (начиная с C++
) и директивы #s 10seel090 управляют кодом блокировать до первой директивы
#elif
, #elifdef
, #elifndef
(начиная с C++23), #else
, #endif
, не принадлежащей никаким внутренним блокам условной предварительной обработки.
#if
, #ifdef
и #ifndef 9Директивы 0104 проверяют указанное условие (см. ниже) и, если оно оценивается как истинное, компилируют контролируемый блок кода. В этом случае последующие директивы
#else
, #elifdef
, #elifndef
, (начиная с C++23) и #elif
игнорируются. В противном случае, если указанное условие оценивается как ложное, контролируемый блок кода пропускается и последующая директива #else
, #elifdef
, #elifndef
, (начиная с C++ 23) или #elif
(если есть) обрабатывается. Если последующая директива равна #else
, безоговорочно компилируется блок кода, управляемый директивой #else
. В противном случае директива #elif
, #elifdef
или #elifndef
(начиная с C++23) действует так, как если бы это была директива #if
: проверяет условие, компилирует или пропускает контролируемый блок кода на основе результат, и в последнем случае обрабатывает последующие #elif
, #elifdef
, #elifndef
, (начиная с C++23) и #else 9директивы 0104. Блок условной предварительной обработки завершается директивой
#endif
.
Выражение может содержать:
определены
идентификатор или определены (
идентификатор )
. Результат равен 1, если идентификатор был определен как имя макроса, в противном случае результат равен 0. После всех макрорасширений и вычислений определены выражения
, __has_include
(начиная с C++17) и __has_cpp_attribute
(начиная с C++20), любой идентификатор, который не является логическим литералом, заменяется на число 0 (сюда входят идентификаторы, которые лексически являются ключевыми словами, но не альтернативные токены, такие как и).
Затем выражение оценивается как интегральное константное выражение.
Если выражение оценивается как ненулевое значение, блок контролируемого кода включается и в противном случае пропускается.
Примечание. До решения проблемы CWG 1955, #if cond1
... #elif cond2
отличается от #if cond1
. .. #else
, за которым следует #if cond2
, потому что if cond1
истинно, второе #если
пропущено и cond2
не обязательно должен быть правильно сформированным, в то время как #elif
's cond2
должно быть допустимым выражением. Начиная с CWG 1955, #elif
, ведущий к пропущенному блоку кода, также пропускается.
Проверяет, был ли идентификатор определен как имя макроса. Идентификатор
#ifdef
по существу эквивалентен идентификатору #ifdefined
идентификатор.
Идентификатор
#ifndef
практически эквивалентен #if !defined
идентификатор.
Идентификатор | (начиная с C++23) |
Хотя директивы #elifdef
и #elifndef
нацелены на C++23, в реализациях рекомендуется использовать их для более старых языковых режимов в качестве соответствующих расширений.
#define ABCD 2 #include <иопоток> основной () { #ifdef ABCD std::cout << "1: да\n"; #еще std::cout << "1: нет\n"; #endif #ifndef ABCD std::cout << "2: no1\n"; #элиф ABCD == 2 std::cout << "2: да\n"; #еще std::cout << "2: no2\n"; #endif #if !defined(DCBA) && (ABCD < 2*4-3) std::cout << "3: да\n"; #endif // Обратите внимание, что если компилятор не поддерживает #elifdef/#elifndef C++23 // директивы, то будет выбран "неожиданный" блок (см. ниже). #ifdef ЦП std::cout << "4: no1\n"; #elifdef GPU std::cout << "4: no2\n"; #elifndef ОЗУ std::cout << "4: да\n"; // ожидаемый блок #еще std::cout << "4: нет!\n"; // неожиданно выбирает этот блок, пропуская // неизвестные директивы и "прыгающие" напрямую // из "#ifdef CPU" в этот блок "#else" #endif // Чтобы решить описанную выше проблему, мы можем условно определить // макрос ELIFDEF_SUPPORTED, только если директивы C++23 // #elifdef/#elifndef поддерживаются.