Директивы препроцессора
В C# определен ряд директив препроцессора, оказывающих влияние на интерпретацию исходного кода программы компилятором. Эти директивы определяют порядок интерпретации текста программы перед ее трансляцией в объектный код в том исходном файле, где они появляются. Термин директива препроцессора появился в связи с тем, что подобные инструкции по традиции обрабатывались на отдельной стадии компиляции, называемой препроцессором. Обрабатывать директивы на отдельной стадии препроцессора в современных компиляторах уже не нужно, но само ее название закрепилось.
Все директивы препроцессора начинаются со знака #. Кроме того, каждая директива препроцессора должна быть выделена в отдельную строку кода. Принимая во внимание современную объектно-ориентированную архитектуру языка C#, потребность в директивах препроцессора в нем не столь велика, как в языках программирования предыдущих поколений. Тем не менее они могут быть иногда полезными, особенно для условной компиляции. В этой статье все директивы препроцессора рассматриваются по очереди.
Директива #define
Директива #define определяет последовательность символов, называемую идентификатором. Присутствие или отсутствие идентификатора может быть определено с помощью директивы #if или #elif и поэтому используется для управления процессом компиляции. Ниже приведена общая форма директивы #define:
Обратите внимание на отсутствие точки с запятой в конце этого оператора. Между директивой #define и идентификатором может быть любое количество пробелов, но после самого идентификатора должен следовать только символ новой строки. Так, для определения идентификатора EXPERIMENTAL служит следующая директива:
В C/C++ директива #define может использоваться для подстановки исходного текста, например для определения имени значения, а также для создания макрокоманд, похожих на функции. А в C# такое применение директивы #define не поддерживается. В этом языке директива #define служит только для определения идентификатора.
Директивы #if и #endif
Обе директивы, #if и #endif, допускают условную компиляцию последовательности кода в зависимости от истинного результата вычисления выражения, включающего в себя один или несколько идентификаторов. Идентификатор считается истинным, если он определен, а иначе — ложным. Так, если идентификатор определен директивой #define, то он будет оценен как истинный. Ниже приведена общая форма директивы #if:
Если идентификаторное_выражение, следующее после директивы #if, истинно, то компилируется код (последовательность операторов), указываемый между ним и директивой #endif. В противном случае этот промежуточный код пропускается. Директива #endif обозначает конец блока директивы #if. Идентификаторное выражение может быть простым, как наименование идентификатора. В то же время в нем разрешается применение следующих операторов: !, ==, !=, && и ||, а также круглых скобок.
Ниже приведен пример применения упомянутых выше директив:

Директивы #else и #elif
Директива #else действует аналогично условному оператору else языка C#, определяя альтернативный ход выполнения программы, если этого не может сделать директива #if.
Обозначение #elif означает «иначе если», а сама директива #elif определяет последовательность условных операций if-else-if для многовариантной компиляции. После директивы #elif указывается идентификаторное выражение. Если это выражение истинно, то компилируется следующий далее кодовый блок, а остальные выражения директивы #elif не проверяются. В противном случае проверяется следующий по порядку блок. Если же ни одну из директив #elif не удается выполнить, то при наличии директивы #else выполняется последовательность кода, связанная с этой директивой, а иначе не компилируется ни один из кодовых блоков директивы #if.
Ниже приведена общая форма директивы #elif:
Давайте добавим в предыдущий пример следующий код:
Директива #undef
С помощью директивы #undef удаляется определенный ранее идентификатор. Это, по существу, означает, что он становится «неопределенным». Ниже приведена общая форма директивы #undef:
Рассмотрим следующий пример кода
Директива #undef применяется главным образом для локализации идентификаторов только в тех фрагментах кода, в которых они действительно требуются.
Директива #error
Директива #error вынуждает компилятор прервать компиляцию. Она служит в основном для отладки. Ниже приведена общая форма директивы #error:
Когда в коде встречается директива #error, выводится сообщение об ошибке. Например, когда компилятору встречается строка кода « #error Это тестовая ошибка! » компиляция прерывается и выводится сообщение «Это тестовая ошибка!».
Директива #warning
Директива #warning действует аналогично директиве #error, за исключением того, что она выводит предупреждение, а не ошибку. Следовательно, компиляция не прерывается. Ниже приведена общая форма директивы #warning:
Директива #line
Директива #line задает номер строки и имя файла, содержащего эту директиву. Номер строки и имя файла используются при выводе ошибок или предупреждений во время компиляции. Ниже приведена общая форма директивы #line:
Имеются еще два варианта директивы #line. В первом из них она указывается с ключевым словом default, обозначающим возврат нумерации строк в исходное состояние, как в приведенном ниже примере:
#line default
А во втором варианте директива #line указывается с ключевым словом hidden. При пошаговой отладке программы строки кода, находящиеся между директивой #line hidden и следующей директивой #line без ключевого слова hidden, пропускаются отладчиком.
Директивы #region и #endregion
С помощью директив #region и #endregion определяется область, которая разворачивается или сворачивается при структурировании исходного кода в интегрированной среде разработки Visual Studio. Ниже приведена общая форма этих директив:
где текст обозначает необязательную символьную строку.
Директива #pragma
С помощью директивы #pragma инструкции задаются компилятору в виде опций. Ниже приведена общая форма этой директивы:
где опция обозначает инструкцию, передаваемую компилятору.
В текущей версии C# предусмотрены две опции для директивы #pragma. Первая из них, warning, служит для разрешения или запрета отдельных предупреждений со стороны компилятора. Она принимает две формы:
где предупреждения обозначает разделяемый запятыми список номеров предупреждений. Для отмены предупреждения используется опция disable, а для его разрешения — опция restore.
Например, в приведенной ниже директиве #pragma запрещается выдача предупреждения №168, уведомляющего о том, что переменная объявлена, но не используется:
Второй для директивы #pragma является опция checksum. Она служит для формирования контрольной суммы в проектах ASP.NET. Ниже приведена ее общая форма:
где имя_файла обозначает конкретное имя файла; GUID — глобально уникальный идентификатор, с которым связано имя_файла; контрольная_сумма — шестнадцатеричное число, представляющее контрольную сумму. У этой контрольной суммы должно быть четное число цифр.
Что означают #define и %% в printf?
Всем привет, я новичок в Си, можете объяснить пару вещей.
Что такое #define и «c чем его едят»?(Это вторая строчка кода)
Что выводит printf при строке форматирования «%.2f%%»? (последняя строчка)
![]()
#define — это директива препроцессора, программы подготавливающей код программы на языке C/C++ к компиляции.
Директива #define служит для замены часто использующихся констант, ключевых слов, операторов или выражений некоторыми идентификаторами.
В вашем случае код, написанный вами будет заменен на:
Более сложный пример для понимания:
Что касается printf , то первым аргументом является строка формата вывода.
Define c что это
Директива #define определяет идентификатор и последовательность символов, которые будут подставляться вместо идентификатора каждый раз, когда он встретится в исходном файле. Формальное определение директивы:
Используем директиву #define:
Здесь определен один идентификатор N. В программе, где встречается этот идентификатор, он будет заменяться на число 23. Например, строка
после обработки препроцессором будет иметь следующий код
Более сложный пример
Здесь определены три идентификатора BEGIN, END, N. В итоге все вхождения последовательности символов «BEGIN» будут заменяться на открывающую фигурную скобку, а «END» — на закрывающую, а символ «N» на число 23.
Таким образом, после обработки препроцессора функция main приобретет следующий вид:
#define также может определять более сложные выражения. Например:
В данном случае выражение ADD(a,b) будет заменяться операцией сложения двух чисел (a + b)
Особенно удобно использовать директиву #define для определения размеров массивов:
В данном случае если мы захотим глобально поменять размер массива, то достаточно изменить значение N в директиве define.
Следует учитывать, что директива препроцессор не заменяет последовательности символов в двойных и одинарных кавычках и в комментариях:
Причем если идентификатор должен представлять одно слово, то его последовательность символов может состоять из нескольких слов или символов, разделенных пробелами:
Директива #undef
В процессе работы мы можем многократно определять новое значение для одного идентификатора:
Но некоторые компиляторы, в частности, gcc, могут выдавать предупреждения при повторном определении идентификатора, и чтобы выйти из этой ситуации, мы можем использовать директиву #undef для отмены действия макроса. Эта директива имеет следующее определение:
Директивы препроцессора в Си
Препроцессор — это специальная программа, являющаяся частью компилятора языка Си. Она предназначена для предварительной обработки текста программы. Препроцессор позволяет включать в текст программы файлы и вводить макроопределения.
Работа препроцессора осуществляется с помощью специальных директив (указаний). Они отмечаются знаком решетка #. По окончании строк, обозначающих директивы в языке Си, точку с запятой можно не ставить.
Основные директивы препроцессора
#include — вставляет текст из указанного файла
#define — задаёт макроопределение (макрос) или символическую константу
#undef — отменяет предыдущее определение
#if — осуществляет условную компиляцию при истинности константного выражения
#ifdef — осуществляет условную компиляцию при определённости символической константы
#ifndef — осуществляет условную компиляцию при неопределённости символической константы
#else — ветка условной компиляции при ложности выражения
#elif — ветка условной компиляции, образуемая слиянием else и if
#endif — конец ветки условной компиляции
#line — препроцессор изменяет номер текущей строки и имя компилируемого файла
#error — выдача диагностического сообщения
#pragma — действие, зависящее от конкретной реализации компилятора.
Директива #include
Директива #include позволяет включать в текст программы указанный файл. Если заголовочный файл содержит описание библиотечных функций и находится в папке компилятора, он заключается в угловые скобки <> .
Если файл находится в текущем каталоге проекта, он указывается в кавычках "" . Для файла, находящегося в другом каталоге необходимо в кавычках указать полный путь.