Что такое директива в программировании
Перейти к содержимому

Что такое директива в программировании

  • автор:

Директива (программирование)

В программировании термин «директива» (указание) по использованию похож на термин «команда», так как также используется для описания некоторых конструкций языка программирования (то есть указаний компилятору или ассемблеру особенностей обработки при компиляции).

Язык ассемблера

В языке ассемблера директивы указывают общую информацию, такую как целевая среда, указание границ между секциями и так далее. Например, директива «ALIGN», которая вставляет в текущую секцию необходимое количество байт для выравнивания строк, часто упоминаемая как «директива», противоречит тому факту, что она совпадает с частями конструкций в генерируемом коде.

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

В языки программирования Си и C++ встроена поддержка препроцессора. Строки в исходном коде, которые должны быть обработаны препроцессором в виде #define и #include , называются препроцессорными директивами.

Синтаксические конструкции, похожие на препроцессорные директивы языка Си, такие как #region в языке C#, также часто называются «директивами», хотя в указанных случаях стадии обработки препроцессором может и не быть.

В других языках высокого уровня

В языке Ada директивы компилятора называются прагмами (сокращение от «pragmatic information» («полезная информация»)).

В Паскале директивы называются указательными комментариями из-за того, что по синтаксису похожи на комментарии. В Паскале указательный комментарий — это комментарий, у которого первым символом указан знак доллара; например, аналогом директивы #include «file» языка Си будет указательный комментарий .

В Perl ключевое слово « use » («применять») можно использовать как «прагму», например use strict; или use utf8; . Такая конструкция иногда может упоминаться как «директива». Тем не менее, в некоторых источниках[1] используется термин «директивы Perl» для обозначения конструкций типа hashbang.

Дополнительные материалы

  • пример использования директив в языке Ассемблера
  • описание использования директив в языке Фортран
  • описание использования директив в языке C—
  • Язык программирования Си
  • Концепции языков программирования
  • Препроцессоры

Wikimedia Foundation . 2010 .

Директива (программирование)

В программировании термин «директива» (указание) по использованию похож на термин «команда», так как также используется для описания некоторых конструкций языка программирования (то есть указаний компилятору или ассемблеру особенностей обработки при компиляции).

Связанные понятия

Зарезерви́рованное сло́во (или ключево́е сло́во) — в языках программирования слово, имеющее специальное значение. Идентификаторы с такими именами запрещены.

Объе́ктный мо́дуль (также — объектный файл, англ. object file) — файл с промежуточным представлением отдельного модуля программы, полученный в результате обработки исходного кода компилятором. Объектный файл содержит в себе особым образом подготовленный код (часто называемый двоичным или бинарным), который может быть объединён с другими объектными файлами при помощи редактора связей (компоновщика) для получения готового исполнимого модуля либо библиотеки.

Динамическая идентификация типа данных (англ. run-time type information, run-time type identification, RTTI) — механизм в некоторых языках программирования, который позволяет определить тип данных переменной или объекта во время выполнения программы.

Кома́нда — это указание компьютерной программе действовать как некий интерпретатор для решения задачи. В более общем случае, команда — это указание некоему интерфейсу командной строки, такому как shell.

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

Упоминания в литературе

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

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

С середины 1990-х годов активно решались вопросы нормативного регулирования применения электронной подписи. Так, в течение 10 лет, с 1995 по 2005 г., практически все страны мира приняли соответствующие законы – «Об электронном документе», «Об электронной подписи», «О цифровой подписи», «Об электронной цифровой подписи», «Об электронных сделках», «Об электронной коммерции» и т. д. [167, с. 131–132]. Особо следует выделить модельные акты, принятые международными организациями: Комиссией ООН по международному торговому праву (ЮНСИТРАЛ) (модельные законы «Об электронной торговле» 1996 г. и «Об электронных подписях» 2001 г.) и Европейским парламентом (Директива 1999/93/ЕС Европейского парламента и Совета от 13 декабря 1999 г. о порядке использования электронных подписей в Европейском сообществе), послужившие в дальнейшем в качестве типовых для разработки национальных законов [231, 233, 234]. Выделим также принятый уже на новом этапе Европейским парламентом и Советом нормативно-правовой акт (EU Regulation) № 910-2014 от 23 июля 2014 г. «Об электронной идентификации и услугах доверия для электронных транзакций на внутреннем рынке, и об отмене Директивы 199 9/93/ЕС» [232].

Связанные понятия (продолжение)

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

Макрокоманда, макроопределение или мáкрос — программный алгоритм действий, записанный пользователем. Часто макросы применяют для выполнения рутинных действий. А также макрос — это символьное имя в шаблонах, заменяемое при обработке препроцессором на последовательность символов, например: фрагмент html-страницы в веб-шаблонах, или одно слово из словаря синонимов в синонимизаторах.

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

Низкоуровневый язык программирования (язык программирования низкого уровня) — язык программирования, близкий к программированию непосредственно в машинных кодах используемого реального или виртуального (например, байт-код, Microsoft .NET) процессора. Для обозначения машинных команд обычно применяется мнемоническое обозначение. Это позволяет запоминать команды не в виде последовательности двоичных нулей и единиц, а в виде осмысленных сокращений слов человеческого языка (обычно английских).

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

Конста́нта в программировании — способ адресации данных, изменение которых рассматриваемой программой не предполагается или запрещается.

Интроспекция (англ. type introspection) в программировании — возможность запросить тип и структуру объекта во время выполнения программы. Особое значение имеет в языке Objective C, однако имеется почти во всех языках, позволяющих манипулировать типами объектов как объектами первого класса; среди языков, поддерживающих интроспекцию — C++ (с RTTI), Go, Java, JavaScript, Perl, Ruby, Smalltalk; в PHP и Python интроспекция интегрирована в сам язык. Интроспекция может использоваться для реализации ad-hoc-полиморфизма.

Среда выполнения (англ. execution environment, иногда «ранта́йм» от англ. runtime — «время выполнения») в информатике — вычислительное окружение, необходимое для выполнения компьютерной программы и доступное во время выполнения компьютерной программы. В среде выполнения, как правило, невозможно изменение исходного текста программы, но может наличествовать доступ к переменным окружения операционной системы, таблицам объектов и модулей разделяемых библиотек.

Интерпретируемый язык программирования — язык программирования, исходный код на котором выполняется методом интерпретации. Классифицируя языки программирования по способу исполнения, к группе интерпретируемых относят языки, в которых операторы программы друг за другом отдельно транслируются и сразу выполняются (интерпретируются) с помощью специальной программы-интерпретатора (что противопоставляется компилируемым языкам, в которых все операторы программы заранее оттранслированы в объектный код.

Стандартная библиотека языка программирования — набор модулей, классов, объектов, констант, глобальных переменных, шаблонов, макросов, функций и процедур, доступных для вызова из любой программы, написанной на этом языке и присутствующих во всех реализациях языка.

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

Блок (также говорят блок кода, блок команд, блок инструкций) в программировании — это логически сгруппированный набор идущих подряд инструкций в исходном коде программы, является основой парадигмы структурного программирования.

Реентерабельность тесно связана с безопасностью функции в многопоточной среде (thread-safety), тем не менее, это разные понятия. Обеспечение реентерабельности является ключевым моментом при программировании многозадачных систем, в частности, операционных систем.

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

Каламбур типизации является прямым нарушением типобезопасности. Традиционно возможность построить каламбур типизации связывается со слабой типизацией, но и некоторые сильно типизированные языки или их реализации предоставляют такие возможности (как правило, используя в связанных с ними идентификаторах слова unsafe или unchecked). Сторонники типобезопасности утверждают, что «необходимость» каламбуров типизации является мифом.

Ме́тод в объектно-ориентированном программировании — это функция или процедура, принадлежащая какому-то классу или объекту.

Раскрутка компилятора (англ. bootstrapping — от boot и strap) — метод создания транслятора для некоторого языка программирования, при котором транслятор пишется на том же языке программирования, для трансляции которого создаётся; создание транслятором исполняемых файлов из исходного кода самого транслятора. Используется для переноса трансляторов на новые платформы. Появился в середине 1950-х годов. Позволяет создать транслятор, который генерирует сам себя. Применялся для создания трансляторов многих.

Переменная среды́ (англ. environment variable) — текстовая переменная операционной системы, хранящая какую-либо информацию — например, данные о настройках системы.

Дестру́ктор — специальный метод класса, служащий для деинициализации объекта (например освобождения памяти).

Шебанг (англ. shebang, sha-bang, hashbang, pound-bang, or hash-pling) — в программировании последовательность из двух символов: решётки и восклицательного знака («#!») в начале файла скрипта.

Идиома программирования — устойчивый способ выражения некоторой составной конструкции в одном или нескольких языках программирования. Идиома является шаблоном решения задачи, записи алгоритма или структуры данных путём комбинирования встроенных элементов языка.

Механизм копирования при записи (англ. Copy-On-Write, COW) используется для оптимизации многих процессов, происходящих в операционной системе, таких как, например, работа с оперативной памятью или файлами на диске (пример — ext3cow).

Станда́рт оформле́ния ко́да (станда́рт коди́рования, стиль программи́рования) (англ. coding standards, coding convention или programming style) — набор правил и соглашений, используемых при написании исходного кода на некотором языке программирования. Наличие общего стиля программирования облегчает понимание и поддержание исходного кода, написанного более чем одним программистом, а также упрощает взаимодействие нескольких человек при разработке программного обеспечения.

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

Побо́чные эффе́кты (англ. side effects) — любые действия работающей программы, изменяющие среду выполнения (англ. execution environment). Например, к побочным эффектам относятся.

Из-за путаницы с терминологией словом «оператор» в программировании нередко обозначают операцию (англ. operator), см. Операция (программирование).Инстру́кция или опера́тор (англ. statement) — наименьшая автономная часть языка программирования; команда или набор команд. Программа обычно представляет собой последовательность инструкций.

Мо́дульное программи́рование — это организация программы как совокупности небольших независимых блоков, называемых модулями, структура и поведение которых подчиняются определённым правилам. Использование модульного программирования позволяет упростить тестирование программы и обнаружение ошибок. Аппаратно-зависимые подзадачи могут быть строго отделены от других подзадач, что улучшает мобильность создаваемых программ.

А́дресное пространство (англ. address space) — совокупность всех допустимых адресов каких-либо объектов вычислительной системы — ячеек памяти, секторов диска, узлов сети и т. п., которые могут быть использованы для доступа к этим объектам при определенном режиме работы (состоянии системы).

Сопрограммы (англ. coroutines) — методика связи программных модулей друг с другом по принципу кооперативной многозадачности: модуль приостанавливается в определённой точке, сохраняя полное состояние (включая стек вызовов и счётчик команд), и передаёт управление другому. Тот, в свою очередь, выполняет задачу и передаёт управление обратно, сохраняя свои стек и счётчик.

Соглашение о вызове (англ. calling convention) — описание технических особенностей вызова подпрограмм, определяющее.

Путь (англ. path) — набор символов, показывающий расположение файла или каталога в файловой системе.

Разделяемая память (англ. Shared memory) является самым быстрым средством обмена данными между процессами.

По́ле кла́сса или атрибу́т (переменная-член, data member, class field, instance variable) в объектно-ориентированном программировании — переменная, связанная с классом или объектом. Все данные объекта хранятся в его полях. Доступ к полям осуществляется по их имени. Обычно тип данных каждого поля задаётся в описании класса, членом которого является поле.

Кросс-компиля́тор (англ. cross compiler) — компилятор, производящий исполняемый код для платформы, отличной от той, на которой исполняется сам кросс-компилятор. Такой инструмент бывает полезен, когда нужно получить код для платформы, экземпляров которой нет в наличии, или в случаях когда компиляция на целевой платформе невозможна или нецелесообразна (например, это касается мобильных систем или микроконтроллеров с минимальным объёмом памяти).

Дизассе́мблер (от англ. disassembler ) — транслятор, преобразующий машинный код, объектный файл или библиотечные модули в текст программы на языке ассемблера.

В программировании сборка мусора (англ. garbage collection) — одна из форм автоматического управления памятью. Специальный процесс, называемый сборщиком мусора (англ. garbage collector), периодически освобождает память, удаляя объекты, которые уже не будут востребованы приложениями.

Ошибка сегментации (англ. Segmentation fault, сокр. segfault, жарг. сегфолт) — ошибка программного обеспечения, возникающая при попытке обращения к недоступным для записи участкам памяти либо при попытке изменить память запрещённым способом. В системах на основе процессоров Motorola 68000 эти ошибки, как правило, известны как ошибки адреса или шины.

Язы́к запро́сов — это искусственный язык, на котором делаются запросы к базам данных и другим информационным системам, особенно к информационно-поисковым системам.

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

Примитивный (встроенный, базовый) тип — тип данных, предоставляемый языком программирования как базовая встроенная единица языка.

При́месь (англ. mix in) — элемент языка программирования (обычно класс или модуль), реализующий какое-либо чётко выделенное поведение. Используется для уточнения поведения других классов, не предназначен для порождения самостоятельно используемых объектов.

Библиотека стандартных шаблонов (STL) (англ. Standard Template Library) — набор согласованных обобщённых алгоритмов, контейнеров, средств доступа к их содержимому и различных вспомогательных функций в C++.

Динамическое распределение памяти — способ выделения оперативной памяти компьютера для объектов в программе, при котором выделение памяти под объект осуществляется во время выполнения программы.

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

В информатике лексический анализ («токенизация», от англ. tokenizing) — процесс аналитического разбора входной последовательности символов на распознанные группы — лексемы, с целью получения на выходе идентифицированных последовательностей, называемых «токенами» (подобно группировке букв в словах). В простых случаях понятия «лексема» и «токен» идентичны, но более сложные токенизаторы дополнительно классифицируют лексемы по различным типам («идентификатор, оператор», «часть речи» и т. п.). Лексический.

Директивы препроцессора C#

Хотя у компилятора нет отдельного препроцессора, директивы, описанные в этом разделе, обрабатываются так, как если бы он был. Они используются в условной компиляции. В отличие от директив C и C++ вы не можете использовать их для создания макросов. Директива препроцессора должна быть единственной инструкцией в строке.

Контекст, допускающий значение NULL

Директива препроцессора #nullable устанавливает контекст с заметками о допустимости значений NULL и контекст с предупреждениями о допустимости значений NULL. Эта директива определяет, действуют ли заметки, допускающие значение NULL, и могут ли быть заданы предупреждения о допустимости значений NULL. Каждый контекст либо отключен, либо включен.

Оба контекста можно указать на уровне проекта (за пределами исходного кода C#). Директива #nullable управляет контекстами заметок и предупреждений и имеет приоритет над параметрами уровня проекта. Директива задает контексты, которыми управляет, пока другая директива не переопределит ее, или до конца исходного файла.

Ниже приведены результаты использования директив:

  • #nullable disable : задает для отключенных контекстов заметки и предупреждения, допускающие значение NULL.
  • #nullable enable : задает включенные контексты заметки и предупреждения, допускающие значение NULL.
  • #nullable restore : восстанавливает контексты заметки и предупреждения, допускающие значение NULL, в параметры проекта.
  • #nullable disable annotations : задает контекст заметки, допускающий значение NULL, отключенным .
  • #nullable enable annotations : задает для включенного контекста заметки, допускающий значение NULL.
  • #nullable restore annotations : восстанавливает контекст заметки, допускающий значение NULL, в параметры проекта.
  • #nullable disable warnings : задает для отключенного контекста предупреждения, допускающего значение NULL.
  • #nullable enable warnings : задает для включенного контекста предупреждения, допускающего значение NULL.
  • #nullable restore warnings : восстанавливает контекст предупреждения, допускающего значение NULL, в параметры проекта.

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

Для управления условной компиляцией используются четыре директивы препроцессора.

  • #if : открывает условную компиляцию, где код компилируется, только если определен указанный символ.
  • #elif : закрывает предыдущую условную компиляцию и открывает новую на основе того, определен ли указанный символ.
  • #else : закрывает предыдущую условную компиляцию и открывает новую, если указанный символ не определен.
  • #endif : закрывает предыдущую условную компиляцию.

Компилятор C# компилирует код между #if директивой и #endif директивой, только если определен указанный символ или не определен, если ! оператор не используется. В отличие от C и C++, числовое значение символу нельзя назначить. Оператор #if в C# является логическим. Он проверяет только одно условие — определен ли указанный символ. Например, следующий код компилируется при DEBUG определении:

#if DEBUG Console.WriteLine("Debug version"); #endif 

Следующий код компилируется, если MYTEST не определен:

#if !MYTEST Console.WriteLine("MYTEST is not defined"); #endif 

Вы можете использовать операторы == (равенство) и != (неравенство) для проверки значений bool true или false . Значение true означает, что символ определен. Инструкция #if DEBUG имеет то же значение, что и #if (DEBUG == true) . Вы можете использовать операторы && (и), || (или) и ! (не), чтобы узнать, определено ли несколько символов. Можно также группировать символы и операторы при помощи скобок.

#if , а также #else директивы , #endif #elif #define и #undef директивы, позволяют включать или исключать код на основе существования одного или нескольких символов. Условная компиляция может быть полезной при компиляции кода для отладочной сборки или для определенной конфигурации.

Условные директивы, начинающиеся с директивы #if , должны явным образом завершаться директивой #endif . #define позволяет определить символ, чтобы выражение, в качестве которого этот символ передается в директиву #if , при вычислении давало значение true . Символ также можно определить с помощью параметра компилятора DefineConstants. Символ можно отменить с #undef помощью. Символ, создаваемый с помощью #define , будет определен в пределах того файл, в котором он определен. Символ, определенный с помощью DefineConstants или #define , не конфликтует с одноименной переменной. Соответственно, имя переменной не должно передаваться директиве препроцессора, а символ может использоваться только в директиве препроцессора.

Директива #elif позволяет создать составную условную директиву. Выражение #elif будет вычисляться в том случае, если ни одна из предшествующих директив #if или необязательных директив #elif после вычисления выражения не возвращает значение true . Если после вычисления выражения #elif возвращается значение true , компилятор вычисляет весь код между директивой #elif и следующей условной директивой. Например:

#define VC7 //. #if DEBUG Console.WriteLine("Debug build"); #elif VC7 Console.WriteLine("Visual Studio 7"); #endif 

С помощью директивы #else можно создать составную условную директиву со следующим поведением: если ни одно из выражений в предшествующих директивах #if или (необязательно) #elif не принимает значение true , компилятор вычисляет код между директивой #else и последующей директивой #endif . Директива #endif обязательно указывается в качестве следующей директивы препроцессора после #else .

#endif указывает на конец условной директивы, начало которой было задано с помощью директивы #if .

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

Требуемые версии .NET Framework Символы Дополнительные символы
(доступно в пакетах SDK для .NET 5 и более поздних версий)
Символы платформы (доступны только
при указании TFM для конкретной ОС)
.NET Framework NETFRAMEWORK , NET48 NET472 NET471 NET47 NET462 NET461 NET46 NET452 NET451 NET45 NET40 NET35 NET20 NET48_OR_GREATER , NET472_OR_GREATER , NET471_OR_GREATER NET47_OR_GREATER NET462_OR_GREATER NET461_OR_GREATER NET46_OR_GREATER NET452_OR_GREATER NET451_OR_GREATER NET45_OR_GREATER NET40_OR_GREATER NET35_OR_GREATER NET20_OR_GREATER
.NET Standard NETSTANDARD , NETSTANDARD2_1 , NETSTANDARD2_0 NETSTANDARD1_6 NETSTANDARD1_5 NETSTANDARD1_4 NETSTANDARD1_3 NETSTANDARD1_2 NETSTANDARD1_1 NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER , NETSTANDARD2_0_OR_GREATER NETSTANDARD1_6_OR_GREATER NETSTANDARD1_5_OR_GREATER NETSTANDARD1_4_OR_GREATER NETSTANDARD1_3_OR_GREATER NETSTANDARD1_2_OR_GREATER NETSTANDARD1_1_OR_GREATER NETSTANDARD1_0_OR_GREATER
.NET 5+ (и .NET Core) NET , NET8_0 , NET7_0 NET6_0 NET5_0 NETCOREAPP NETCOREAPP3_1 NETCOREAPP3_0 NETCOREAPP2_2 NETCOREAPP2_1 NETCOREAPP2_0 NETCOREAPP1_1 NETCOREAPP1_0 NET8_0_OR_GREATER , NET7_0_OR_GREATER , NET6_0_OR_GREATER NET5_0_OR_GREATER NETCOREAPP3_1_OR_GREATER NETCOREAPP3_0_OR_GREATER NETCOREAPP2_2_OR_GREATER NETCOREAPP2_1_OR_GREATER NETCOREAPP2_0_OR_GREATER NETCOREAPP1_1_OR_GREATER NETCOREAPP1_0_OR_GREATER ANDROID , BROWSER , IOS MACCATALYST MACOS TVOS WINDOWS
[OS][version] (например IOS15_1 ),
[OS][version]_OR_GREATER (например IOS15_1_OR_GREATER )
  • Символы без привязки к версии определены независимо от версии, которую вы хотите использовать в качестве целевой.
  • Символы для определенных версий определены только для тех версий, которые вы хотите использовать в качестве целевых.
  • Символы _OR_GREATER определены для версии, которую вы хотите использовать в качестве целевой, и всех более ранних версий. Например, если вы выбрали .NET Framework 2.0, определяются следующие символы: NET20 , NET20_OR_GREATER , NET11_OR_GREATER и NET10_OR_GREATER .
  • NETSTANDARD__OR_GREATER Символы определяются только для целевых объектов .NET Standard, а не для целевых объектов, реализующих .NET Standard, таких как .NET Core и платформа .NET Framework.
  • Они отличаются от моникеров целевой платформы (TFM), используемых свойством MSBuild TargetFramework и NuGet.

Для традиционных проектов, в которых не используется пакет SDK, необходимо вручную настроить символы условной компиляции для различных целевых платформ в Visual Studio с помощью страниц свойств проекта.

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

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

#define MYTEST using System; public class MyClass < static void Main() < #if (DEBUG && !MYTEST) Console.WriteLine("DEBUG is defined"); #elif (!DEBUG && MYTEST) Console.WriteLine("MYTEST is defined"); #elif (DEBUG && MYTEST) Console.WriteLine("DEBUG and MYTEST are defined"); #else Console.WriteLine("DEBUG and MYTEST are not defined"); #endif >> 

В следующем примере показано, как тестировать разные целевые платформы для использования более новых интерфейсов API, когда это возможно:

public class MyClass < static void Main() < #if NET40 WebClient _client = new WebClient(); #else HttpClient _client = new HttpClient(); #endif >//. > 

Определение символов

Используйте следующие две директивы препроцессора, чтобы определить или отменить определение символов для условной компиляции.

  • #define : определение символа.
  • #undef : подчеркивание символа.

#define позволяет определить символ. При использовании символа в качестве выражения, передаваемого #if директиве, выражение будет оцениваться true , как показано в следующем примере:

#define VERBOSE #if VERBOSE Console.WriteLine("Verbose output version"); #endif 

Директиву #define нельзя использовать для объявления значений констант, как это обычно делается в C и C++. Для определения констант в C# следует использовать статические элементы класса или структуры. При наличии нескольких констант имеет смысл создать для них отдельный класс «Constants».

Символы можно использовать для указания условий компиляции. Вы можете протестировать символ с помощью одного #if или. #elif Для условной компиляции также можно использовать ConditionalAttribute. Вы можете определить символ, но не можете присвоить символу значение. Директива #define должна находиться в файле перед использованием любых инструкций, которые также не являются директивами препроцессора. Символ также можно определить с помощью параметра компилятора DefineConstants. Символ можно отменить с #undef помощью.

Определение областей

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

  • #region : начало области.
  • #endregion : конец области.

Директива #region позволяет указать блок кода, который можно разворачивать и сворачивать с помощью функции структурирования в редакторе кода. В больших файлах кода удобно сворачивать или скрывать одну область или несколько, чтобы не отвлекаться от той части файла, над которой в настоящее время идет работа. В следующем примере показано, как определить область:

#region MyClass definition public class MyClass < static void Main() < >> #endregion 

В конце блока #region должна присутствовать директива #endregion . Блок #region не может накладываться на блок #if . Однако блок #region можно вложить в блок #if , а блок #if — в блок #region .

Сведения об ошибках и предупреждениях

Вы указываете компилятору создавать определенные пользователем ошибки и предупреждения компилятора, а также управлять сведениями о строках с помощью следующих директив.

  • #error : создание ошибки компилятора с указанным сообщением.
  • #warning : создание предупреждения компилятора с конкретным сообщением.
  • #line : изменение номера строки, выводимого с сообщениями компилятора.

#error позволяет создать определяемую пользователем ошибку CS1029 из определенного места в коде. Рассмотрим пример.

#error Deprecated code in this method. 

Компилятор обрабатывает #error version особым образом и сообщает об ошибке компилятора CS8304 с сообщением, содержащим используемые версии компилятора и языка.

#warning позволяет создать предупреждение компилятора CS1030 первого уровня из определенного места в коде. Например:

#warning Deprecated code in this method. 

Директива #line позволяет изменять номер строки компилятора и при необходимости имя файла, в который будут выводиться ошибки и предупреждения.

В следующем примере показано, как включить в отчет два предупреждения, связанные с номерами строк. Директива #line 200 принудительно устанавливает номер следующей строки 200 (по умолчанию используется номер 6). До выполнения следующей директивы #line в отчете будет указываться имя файла Special. Директива #line default по умолчанию восстанавливает нумерацию строк в исходное состояние с учетом строк, номера которых были изменены с помощью предшествующей директивы.

class MainClass < static void Main() < #line 200 "Special" int i; int j; #line default char c; float f; #line hidden // numbering not affected string s; double d; >> 

В результате компиляции формируются следующие результаты:

Special(200,13): warning CS0168: The variable 'i' is declared but never used Special(201,13): warning CS0168: The variable 'j' is declared but never used MainClass.cs(9,14): warning CS0168: The variable 'c' is declared but never used MainClass.cs(10,15): warning CS0168: The variable 'f' is declared but never used MainClass.cs(12,16): warning CS0168: The variable 's' is declared but never used MainClass.cs(13,16): warning CS0168: The variable 'd' is declared but never used 

Директива #line может использоваться на автоматизированном промежуточном этапе процесса построения. Например, если строки были удалены из первоначального файла с исходным кодом, но вам по-прежнему требуется создавать выходные файлы компилятора на основе изначальной нумерации строк в файле, можно удалить строки и затем смоделировать их первичную нумерацию с помощью директивы #line .

Директива #line hidden скрывает последующие строки для отладчика. В этом случае при пошаговой проверке кода разработчиком все строки между #line hidden и следующей директивой #line (кроме случаев, когда это также директива #line hidden ) будут пропущены. Этот параметр также можно использовать для того, чтобы дать ASP.NET возможность различать определяемый пользователем и создаваемый компьютером код. В основном эта функция используется в ASP.NET, но также может быть полезна и в других генераторах исходного кода.

Директива #line hidden не влияет на имена файлов и номера строк в отчетах об ошибках. Это значит, что при обнаружении ошибки в скрытом блоке компилятор укажет в отчете текущие имя файла и номер строки, где найдена ошибка.

Директива #line filename задает имя файла, которое будет отображаться в выходных данных компилятора. По умолчанию используется фактическое имя файла с исходным кодом. Имя файла должно заключаться в двойные кавычки (» «). Перед ним должен указываться номер строки.

Начиная с C# 10 можно использовать новую форму директивы #line :

#line (1, 1) - (5, 60) 10 "partial-class.cs" /*34567*/int b = 0; 

Компоненты этой формы:

  • (1, 1) : начальная строка и столбец для первого символа строки, следующей за директивой. В этом примере следующая строка будет отображаться как строка 1, столбец 1.
  • (5, 60) : конечная строка и столбец для помеченной области.
  • 10 : смещение столбца, чтобы директива #line вступила в силу. В этом примере в качестве столбца 1 будет отображаться десятый столбец. Здесь начинается объявление int b = 0; . Это поле необязательно. Если этот параметр опущен, директива вступает в силу в первом столбце.
  • «partial-class.cs» : имя выходного файла.

В предыдущем примере будет создано следующее предупреждение:

partial-class.cs(1,5,1,6): warning CS0219: The variable 'b' is assigned but its value is never used 

После повторного сопоставления переменная b , находится в первой строке в символе шесть из файла partial-class.cs .

Предметно-ориентированные языки (DSL) обычно используют этот формат, чтобы обеспечить более эффективное сопоставление исходного файла с созданными выходными данными C#. Чаще всего эта расширенная #line директива используется для повторного сопоставления предупреждений или ошибок, которые отображаются в созданном файле исходному источнику. Например, рассмотрим эту страницу razor:

@page "/" Time: @DateTime.NowAndThen 

Свойство DateTime.Now было введено неправильно DateTime.NowAndThen . Созданный C# для этого фрагмента razor выглядит следующим образом: page.g.cs

 _builder.Add("Time: "); #line (2, 6) (2, 27) 15 "page.razor" _builder.Add(DateTime.NowAndThen); 

Выходные данные компилятора для предыдущего фрагмента кода:

page.razor(2, 2, 2, 27)error CS0117: 'DateTime' does not contain a definition for 'NowAndThen' 

Строка 2, столбец 6 в page.razor том, где начинается текст @DateTime.NowAndThen . Это отмечено (2, 6) в директиве. Этот диапазон заканчивается в строке @DateTime.NowAndThen 2, столбце 27. Это отмечается (2, 27) в директиве. Текст начинается DateTime.NowAndThen в столбце 15 page.g.cs . Это отмечается 15 в директиве. Объединение всех аргументов и компилятор сообщает об ошибке в его расположении page.razor . Разработчик может перейти непосредственно к ошибке в исходном коде, а не к созданному источнику.

Дополнительные примеры этого формата см. в разделе примеров в спецификации функции.

Директивы pragma

Директива #pragma предоставляет компилятору специальные инструкции для компиляции файла, в котором она появляется. Компилятор должен поддерживать эти инструкции. Другими словами, директиву #pragma невозможно использовать для создания настраиваемых инструкций предварительной обработки.

  • #pragma warning : включение или отключение предупреждений.
  • #pragma checksum : создание контрольной суммы.
#pragma pragma-name pragma-arguments 

pragma-name — имя распознанной прагмы, а pragma-arguments — аргументы, относящиеся к прагме.

#pragma warning

#pragma warning может включать или отключать определенные предупреждения.

#pragma warning disable warning-list #pragma warning restore warning-list 

warning-list — список номеров предупреждений с разделителем-запятой. Префикс CS является необязательным. Если номера предупреждений не указаны, disable отключает все предупреждения, а restore включает все предупреждения.

Чтобы найти номера предупреждений в Visual Studio, выполните сборку проекта, а затем поиск номеров предупреждений в окне Вывод.

Параметр disable вступает в силу, начиная со следующей строки исходного файла. Предупреждение восстанавливается в строке после restore . Если в файле нет restore , предупреждения восстанавливаются до их состояния по умолчанию в первой строке всех последующих файлов в той же компиляции.

// pragma_warning.cs using System; #pragma warning disable 414, CS3021 [CLSCompliant(false)] public class C < int i = 1; static void Main() < >> #pragma warning restore CS3021 [CLSCompliant(false)] // CS3021 public class D < int i = 1; public static void F() < >> 

#pragma checksum

Создает контрольные суммы для исходных файлов, чтобы помочь с отладкой страниц ASP.NET.

#pragma checksum "filename" "" "checksum bytes" 

«filename» — это имя файла, для которого требуется наблюдение за изменениями или обновлениями, «» — глобальный уникальный идентификатор (GUID) для хэш-алгоритма, а «checksum_bytes» — строка шестнадцатеричных цифр, представляющих байты контрольной суммы. Должно быть четным числом шестнадцатеричных цифр. Нечетное число цифр приведет к выводу предупреждения во время компиляции, и директива будет пропущена.

Отладчик Visual Studio использует контрольную сумму, чтобы подтвердить нахождение правильного источника. Компилятор вычисляет контрольную сумму для исходного файла, а затем передает результат в файл базы данных (PDB) программы. Отладчик затем использует PDB-файл для сравнения с контрольной суммой, вычисленной им для исходного файла.

Это решение не работает для проектов ASP.NET, так как рассчитанная контрольная сумма относится к созданному исходному файлу, а не файлу ASPX. Чтобы решить эту проблему, #pragma checksum предоставляет поддержку контрольных сумм для страниц ASP.NET.

При создании проекта ASP.NET в Visual C# созданный исходный файл содержит контрольную сумму для ASPX-файла, из которого создается источник. Затем компилятор записывает эти данные в PDB-файл.

Если компилятор не обнаруживает директиву #pragma checksum в файле, он вычисляет контрольную сумму и записывает значение в PDB-файл.

class TestClass < static int Main() < #pragma checksum "file.cs" "" "ab007f1d23d9" // New checksum > > 

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Что такое директива в программировании

Директива #define

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

Стоит упомянуть о некотором нежелательном эффекте, который может иметь место при использовании директивы #define. Например, если имя константы, заданное с помощью директивы #define включить в имя другой константы или переменной, то оно будет заменено на свое значение.

В общем случае рекомендуется использовать выражение const для определения констант вместо #define

Синтаксис для Arduino такой же как и для C:

Синтаксис:

#define constantName value

Внимание! Символ # перед словом define обязателен.

Пример

#define ledPin 3 // компилятор заменит любое упоминание ledPin на занчение 3 во время компиляции

Замечание по использованию

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

#define ledPin 3; // это ошибка, ; здесь не нужна

Точно так же знак равно после имени константы тоже вызовет критическую ошибку компилятора.

#define ledPin = 3 // это тоже ошибка, знак = не нужен

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *