$Warnings — Директива компилятора Delphi

Директивы компилятора

директивы условной компиляции

<$C+>и <$C->— директивы проверки утверждений
<$I+>и <$I->— директивы контроля ввода/вывода
<$M>и <$S>— директивы, определяющие размер стека
<$M+>и <$M->— директивы информации времени выполнения о типах
<$Q+>и <$Q->— директивы проверки переполнения целочисленных операций
<$R>— директива связывания ресурсов
<$R+>и <$R->— директивы проверки диапазона
<$APPTYPE CONSOLE>— директива создания консольного приложения

1) Директивы компилятора, разрешающие или запрещающие проверку утверждений

По умолчанию <$C+>или

Область действия локальная

Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует

директива <$C+>и процедура Assert генерирует исключение EAssertionFailed, если проверяемое утверждение ложно.

Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.

Директивы действуют на весь файл исходного кода независимо от того, в каком месте файла они расположены.

2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода

По умолчанию <$I+>или

Область действия локальная

Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal. Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try. except, имеющем обработчик исключения EInOutError. Если такого блока нет, то обработка производится методом TApplication.HandleException.

Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult. Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:

В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.

3) Директивы компилятора, определяющие размер стека

Область действия глобальная

Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека. Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантированно имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.

Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow. Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize директивы <$M>или параметром number директивы <$MINSTACKSIZE>.

Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number>. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.

В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.

4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах (runtime type information — RTTI)

По умолчанию <$M->или

Область действия локальная

Директивы компилятора $I включают или выключают генерацию информации времени выполнения о типах (runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published. В противном случае раздел published в классе не допускается. Класс TPersistent, являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.

5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях

По умолчанию <$Q->или

Область действия локальная

Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs, Sqr, Succ, Pred, Inc и Dec. После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение, то генерируется исключение EIntOverflow. Если это исключение не может быть обработано, выполнение программы завершается.

Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании. Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.

6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.

При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и сгенерируется исключение EResNotFound.

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

По умолчанию <$R->или

Область действия локальная

Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError. Если оно не может быть перехвачено, выполнение программы завершается.

Проверка диапазона длинных строк типа Long strings не производится. Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.

8) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.

При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и сгенерируется исключение EResNotFound.

Delphi. Условная компиляция. Краткий справочник

Условная компиляция предназначена для управления компиляцией программного кода. В Delphi имеется несколько способов её реализации, но в основном используются только четыре.

В этой реализации условная директива <$IFDEF …>проверяет, был ли определён указанный в ней символ условной компиляции. Если да, то код программы между директивами <$IFDEF …>и <$ENDIF>компилируется. В противном случае, код между этими двумя директивами компилироваться не будет.

Эта реализация отличается от предыдущей наличием директивы <$ELSE>. В этом случае, если условный оператор определён, будет компилироваться код программы между директивами <$IFDEF>и <$ELSE>. В противном случае, будет компилироваться код программы между директивами <$ELSE>и <$ENDIF>.

По сути, первая и вторая реализации ведут себя как краткая и полная форма обычного условного оператора if.

Как определить символ условной компиляции? Для этого также существует два способа.

Первый – использование директивы

Второй способ. Определить его в свойствах проекта. Для этого в меню Project нужно выбрать пункт Options и в поле Conditional defines ввести символ условной компиляции.

Третий и четвёртый способы являются аналогией первого и второго соответственно. Отличие в том, что используется условная директива <$IFNDEF>. Эта директива проверяет, что указанный символ не определён. То есть, является прямой противоположностью директивы <$IFDEF>.

В случае <$IFNDEF>, код между этой директивой и <$ENDIF>либо <$ELSE>будет скомпилирован, только если указанный в ней символ условной компиляции не определён. В остальном, принцип реализации аналогичен приведённому для директивы <$IFDEF>:

В Delphi уже имеется ряд символов условной компиляции. Вот их «классический» набор.

Значение
MSWINDOWS Код компилируется только в ОС Windows
WIN32 То же самое, только код компилируется лишь для 32-разядной ОС.
LINUX Был введён в Delphi 6 вместе с MSWINDOWS для определения платформы, для которой необходимо компилировать тот или иной код.Так как компиляция для Linux в Delphi до сих пор отсутствует, то использование этого символа в программах не имеет смысла.
CONSOLE Консольное приложение
CPU386 Компиляция для процессоров типа i386 или более современных. Так как речь идёт о процессорах типа i386, использование данного символа уже давно потеряло актуальность.
CONDITIONAL EXPRESSIONS Проверяет использование директив $IF

Также в число «классических» входит и символ VERxxx, который указывает конкретную версию компилятора. По сути, это целое семейство символов условной компиляции, в которое с выходом новой версии Delphi добавляется новый символ соответствующий этой версии. Ниже представлена таблица соответствия версий Delphi символам условной компиляции VERxxx (материал взят с Исходники.ру).

Символ условной компиляции
1 VER80
2 VER90
3 VER100
4 VER120
5 VER130
6 VER140
7 VER150
8 VER160
2005 VER170
2006 VER180
2007* VER180 или VER185
2009 VER200
2010 VER210
XE VER220
XE2 VER230
XE3 VER240
XE4 VER250
XE5 VER260
XE6 VER270
XE7 VER280
XE8 VER290
10 Seatle VER300
10.1 Berlin VER310
10.2 Tokyo VER320

*-версии 2006 и 2007 совместимы между собой на уровне двоичного кода. Поэтому, для поддержки обеих версий следует использовать символ VER180. Если необходима поддержка только версии 2007, необходимо использовать символ VER185.

После выхода в 2011 году кроссплатформенной библиотеки FireMonkey, были введены новые символы условной компиляции для MacOS и iOS. А, в 2013 году с появлением поддержки Android был введён и специальный символ условной компиляции для этой ОС. Ниже представлен перечень этих символов.

Символ условной компиляции
MacOS MACOS
iOS IOS
Android ANDROID

Условная компиляция на примере кроссплатформенного приложения:

$Warnings — Директива компилятора Delphi

Елена Филиппова, Королевство Дельфи
15 апреля 2003г.

Каждая программа содержит по крайней мере одну ошибку
Народная мудрость

Никогда не делает ошибок тот, кто просто ничего не делает. Это тоже народная мудрость. Поэтому с ошибками в коде сталкивается в своей работе каждый программист. После того, как программа успешно откомпилирована, преодолен первый этап борьбы. :о)

Не секрет, что гораздо сложнее бороться с ошибками, возникающими во время выполнения программы, особенно, когда они приводят не просто к ее «падению», а к неадекватной работе, наслаивая проблемы и создавая «наведенные» ошибки. И здесь уже надежды на компилятор нет. Спасение утопающих, как известно, дело рук этих самых утопающих.

Материал данной статьи не имеет отношения к теме тестирования и отладки. Он предназначен начинающим программистам, дабы обратить их внимание на «соломинку», которую протягивает утопающим IDE Delphi в нелегком деле борьбы с ошибками :о) Ведь не зря же ее называют дружественной средой разработки.

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

Илон Маск рекомендует:  Что такое код pg_affected_rows

Типы сообщений компилятора

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

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

  1. Error — ошибка
  2. Warning — предупреждение
  3. Hint — подсказка или совет.

Довольно распространенное отношение начинающих программистов к этим сообщениям заключается в полном игнорировании предупреждений и советов. Ведь не ошибки же? Программа откомпилирована и запускается на исполнение. И, может быть, даже работает :о)

Мне приходилось встречать на некоторых форумах «дружеские советы» новичкам, сводившиеся к предложению «не обращать на эту ерунду внимания, это оптимизатор у Delphi выделывается.»
Так ли это на самом деле?

При наличии в проекте ошибок-Errors , не будет сформирован исполняемый файл и, волей не волей, ошибки придется исправлять. Наличие же сообщений Hints и Warnings позволяет запускать приложение. Обратите внимание на окно процесса компиляции (рис. 1) , в строке «Done» написано не Compiled , что, в общем-то, ожидалось, а предупреждение There are warnings . Несмотря на отсутствие ошибок, проект откомпилирован с тремя «подсказками» и пятью «предупреждениями».
Насколько безопасно не обращать на это внимание? Начнем с самых безобидных сообщений компилятора, с его советов — Hints .

Безобидные(?) Hints

Ниже приведен код простой функции, которая не содержит синтаксических ошибок, но при её компиляции будет получено три Hint’а (в коде они отмечены красным). Давайте разберем их подробно.

Variable ‘i’ is declared but never used in ‘FunctonName’ Переменная ‘i’ определена, но никогда не используется в ‘FunctonName’ — это одно из самых часто встречающихся сообщений. Чаще всего оно просто говорит о неаккуратном коде. Однако, наличие таких переменных в принципе может означать потенциальную ошибку в реализации алгоритма, ведь зачем-то она была объявлена. Именно поэтому компилятор обращает ваше внимание на эту переменную: вдруг вы просто забыли доделать задуманное?
Простейшее решение — удалить все неиспользованные переменные. А заодно и проверить, действительно ли они не нужны :о)

Value assigned to ‘j’ never used Значение, присвоенное ‘j’ никогда не используется . Это сообщение не означает, что программа неправильная — оно означает только то, что компилятор обнаружил, что после присвоения переменной j значения 0 , эта переменная не участвует более ни в каких операциях. Что делает это присвоение абсолютно бессмысленным. И, если используется оптимизатор, оно будет удалено в откомпилированном коде.
Так же, как и предыдущий Hint, это сообщение чаще всего является признаком «мусора» в коде, от которого следует избавляться, чтобы не пропустить потенциальные ошибки. Опасность в том, что в реальности может оказаться, что это присвоение было сделано не той переменной, которой нужно. Например, надо было присвоить что-то переменной i , а присвоили j .

FOR or WHILE loop executes zero times — deleted Цикл FOR или WHILE исполняется ноль раз — удалено. Собственно, текст этого сообщения полностью объясняет ситуацию. Конечно же это не специально, это «рука дрогнула», «глаз замылился» или что-то в таком духе. И компилятору остается только сказать спасибо.

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

Рассмотренные выше ситуации можно и нужно исправлять. Но бывают случаи, когда нет возможности исправить код так, чтобы не получать Hint’s при компиляции. Рассмотрим небольшой пример по созданию собственных классов:

Overriding virtual method ‘TLists.Clear’ has a lower visibility (private) than base class (public) Переопределенный виртуальный метод ‘TLists.Clear’ имеет видимость ниже, чем в базовом классе Это не то, чтобы ошибка, но на практике понижение видимости свойств и методов класса встречается довольно редко и говорит об ошибках на этапе проектирования базовых классов. Это понижение видимости может создать в проблему в будущем, если от класса TLists будут наследоваться при создании новых классов.

Private symbol ‘FutureTools’ declared but never used Приватный символ ‘FutureTools’ определен, но никогда не используется . Это сообщение сродни уже описанному Variable ‘ ‘ is declared but never used.
Так как этот метод приватный, то он по определению не может быть доступен нигде более, как внутри класса. Тем не менее, компилятор там его использования не обнаруживает. Из чего следует естественный вывод, что функция ‘FutureTools’ нигде не будет использоваться.

Допустим, что в этом случае все не так просто, как это видится компилятору и функция FutureTools, например, нигде не используется вовсе не потому, что вы о ней забыли или она никому не нужна. Возможно это задел на будущее. Можно, конечно, закомментировать и объявление функции и код ее реализации до поры до времени. Но можно сделать и иначе, несколько изящнее.

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

Как раз для таких случаев предусмотрена сцециальная дирректива компилятора: <$HINTS OFF>. Она отключает проверку кода на предмет обнаружения Hint’ов до тех пор, пока в коде не встретится обратная дирректива — <$HINTS ON>. Если в обрамленном этими специальными комментариями коде и будут «опасные» Hint-ситуации, они будут игнорироваться компилятором.

Воспользовавшись этими диррективами, мы получим код, который компилируется не только без ошибок, но и без Hint’ов:

Примечание:
Не поддавайтесь искушению раз и навсегда «заткнуть» с помощью <$HINTS OFF>упрямый компилятор, пользы от этого вам, как программисту, не будет никакой.

О пользе сообщений компилятора

Небольшое лирическое отступление:

В каждом уважающем себя форуме есть список вопросов, признанных как off-topic. Часть из них сто раз уже разжевана, часть решается нажатием клавиши F1 и так далее. На каждом форуме борятся с ними по-своему, но, к огромному сожалению, задающих такие вопросы не становится меньше. Более того, вопрошающие частенько еще и обижаются, когда их отсылают :о) Вот пример классического off-topic’а:

В ответ на такой вопрос, господа, как правило, начинают страшно ругаться. :о) Самые вежливые слова, которые получает автор вопроса, звучат примерно так — «Сколько же можно?! Хелп когда научитесь читать?!» На что автор, как ему кажется, абсолютно справедливо, начинает огрызаться, что типа, откуда ему было знать, что такое абстрактный метод и что на этом самом TStrings не написано, какие у него методы!
Проведем маленький эксперимент и напишем такой код:

При компиляции нам будет выдан warning , как раз на той строке, где создается экземпляр класса — Constructing instance of ‘TStrings’ containing abstract methods . Я надеюсь, что текст этого предупреждения абсолютно ясен и не требует пояснений.

Смотрите, что получается, ошибок компиляции нет, человек с высоко поднятой головой игнорирует «всю эту ерунду» и просто не обращает внимания на предупреждения компилятора! В итоге, он получает ошибку времени выполнения, некоторое личное недоумение, кучу словесных тычков и подзатыльников на форуме. А ведь его предупреждали! :о)

IDE Delphi, как дружественная среда программирования, кроме обычного факта уведомления о сообщениях компилятора, предоставляет дополнительные возможности — если дважды кликнуть на тексте сообщения (рис. 2), то курсор автоматически переместиться на ту строку в редакторе кода, в которой, по мнению компилятора, возникает спорная ситуация. Если же на тексте сообщения ( hint или warning ) нажать F1 , то откроется окно справочной системы (рис. 3) по конкретному hint’у или warning’у. Там будет описано, в каких случаях компилятор выдает такое сообщение и что Delphi вообще «думает» по этому поводу.

Коварные Warnings

Предупреждения- warnings обладают гораздо более высоким уровнем опасности с точки зрения компилятора. История с абстрактным классом служит тому примером. Разберем еще несколько случаев возникновения warning ‘ов: Return value of function ‘VarCompare’ might be undefined Значение результата функции ‘VarCompare’ может быть неопределено .

Казалось бы, с точки зрения логики в тексте функции все верно. Перекрыты все возможные случаи и сообщение компилятора выглядит несколько неуместно. Но не стоит ждать от него слишком много, компилятор не может (да и не обязан) вникать в логику программы. Для того, чтобы избавиться от этого сообщения, было бы правильно переписать это код. Например, вот так:

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

Еще один пример коварного warning ‘а: Variable ‘list’ might not have been initialized Переменная ‘list’ может быть не инициализирована .

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

Method ‘Clear’ hides virtual method of base type ‘TList’ Метод ‘Clear’ прячет виртуальный метод базового класса ‘TList’ . Эта ситуация буквально означает перекрытие виртуального метода родительского класса. То есть, в классе TExLists определен статический метод, имя которого совпадает с виртуальным методом родительского класса TList. Если в дальнейшем, от класса TExLists будут наследоваться, то метод Clear для этих наследников будет закрыт. Правильный вариант:

Точно также, как и в случае с hint’ами, существуют опции для отключения сообщений компилятора о предупреждениях — , и для их включения — . И точно так же хочу обратить внимание на нежелательность использования этих опций без нужды. Молчание компилятора в этом случае не будет означать отсутствие проблемы :о)

Резюме

Цель этого материала, не рассказать обо всех возможных hint ‘ах и warning ‘ах, их список слишком велик для одной статьи, а обратить внимание на необходимость анализировать ВСЕ сообщения компилятора в ваших программах.

Елена Филиппова
Специально для Королевства Delphi

Идентификаторы $ в Delphi WARN директивы компилятора

December 2020

14.4k раз

Delphi имеет $ WARN директивы компилятора, что позволяет селективно включить или отключить конкретные предупреждения. Delphi 2009 файл справки описывает синтаксис:

Но это только перечисляет идентификаторы 6 предупреждений.

Я хотел бы иметь полный список всех идентификаторов предупреждения. В частности, я хочу знать идентификаторы неявной строки литых предупреждений W1057 и W1058 в Delphi 2009.

Мне удалось угадать один для неявного ANSI-> отбрасывает Unicode (W1057):

Погуглить за что нашел меня другой:

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

4 ответы

Что-то еще не упоминается в документации по Delphi 2009:

В $ WARN директивы теперь имеет 3-ий вариант ERROR в дополнение к ON и OFF. Таким образом, вы можете иметь:

Такие вещи, как это должно быть документально

На сегодняшний день полный список идентификаторов и их номеров предупреждения компилятора приведены в документации по адресу:

Выдержка:

Идентификатор в $ WARN директива может иметь любое из следующих значений:

Я посмотрел через помощь и не видел полный список . так ковыряться кода оказывается постоянные предупреждения компилятора все перечисленные в: CodeGear \ RAD Studio \ 6.0 \ Sources \ toolsapi \ DCCStrs.pas

Поиск «Implicit_String_Cast_Loss», и вы увидите, что константа sIMPLICIT_STRING_CAST_LOSS = «DCC_IMPLICIT_STRING_CAST_LOSS»;

Я бы предположил, остальные строки DCC_xxx с соответствующим X_true / _false / _error Определяет то, что вы после этого.

Интернет помощь была не очень хорошо, так как Delphi 7.

Право Darian о том, что DCCStrs.pas перечислены идентификаторы, используемые компилятором Delphi. Это не приходило в голову искать источник, так как Delphi не включает в себя источник для его составителя.

Я извлек идентификаторы для подсказок и предупреждений от этого файла:

Директива компилятора региона Delphi — файлы с совместимостью в обратном направлении?

Учитывая желание использовать полезную директиву компилятора Region в файлах модулей, какой лучший подход позволяет использовать эти же устройства в предыдущих версиях Delphi? Похоже, что нет «приличного» подхода. (Желаемая версия IDE — Delphi 7)

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

Я полагаю, что препроцессор можно было бы написать, чтобы прокомментировать все директивы Region/EndRegion, если используется версия Delphi, которая не поддерживает регионы .. и затем добавляет обратно для более поздних версий?

Я не на 100% перешел на Delphi 2009 и должен поддерживать несколько версий IDE.

Создан 18 апр. 09 2009-04-18 23:34:48 Darian Miller

2 ответа

Я предполагаю, что D7 не хочет переписывать <$ REGION>или <$ ENDREGION>? У меня установлен только D2007/9 и не могу это проверить.

D2009 редактор создает область, как и ожидалось. D7 должен игнорировать $ REGION/$ ENDREGION, если «undef» не определен.

Создан 19 апр. 09 2009-04-19 07:14:16 gabr

+1. Положите на одну строку и создайте с помощью кода или живого шаблона, это не убивает чистоты и не требует больше усилий писать. – mghie 19 апр. 09 2009-04-19 10:36:49

Это работает . и будет отмечен как ответ, как указано в первоначальном вопросе. Мой реальный ответ — удалить Регионы на данный момент и переключить все на 2009, как позволяет время. – Darian Miller 22 апр. 09 2009-04-22 02:38:03

Есть несколько компонентов для улучшения редактора Delphi (7), которые обеспечивают что-то вроде этого. Думаю GExperts.

Если вы в порядке с вашим кодом, вы можете рассмотреть <$ I>, чтобы разделить большие файлы.

Создан 20 апр. 09 2009-04-20 07:39:57 Stijn Sanders

. или просто разделить устройство на несколько единиц! О директиве $ INCLUDE, из моего эксперимента, $ I не работает в среде Delphi. Например, в навигаторе кода есть проблемы с просмотром кода во вложенных файлах. Нет проблем с компилятором, но с Delphi IDE. Напротив, у Lazarus нет проблем при использовании нескольких файлов INCLUDEd и обрабатывать их как обычные .pas-файлы. – Arnaud Bouchez 13 мар. 15 2015-03-13 08:38:37

$Warnings — Директива компилятора Delphi

Как сделать свои собственные сообщения при компилляции

Как узнать версию компиллятора ?

Какие есть директивы компилятора?

<$I+>и <$I->— директивы контроля ввода/вывода
<$M>и <$S>— директивы, определяющие размер стека

<$M+>и <$M->— директивы информации времени выполнения о типах
<$Q+>и <$Q->— директивы проверки переполнения целочисленных операций

<$R>— директива связывания ресурсов

<$R+>и <$R->— директивы проверки диапазона

<$APPTYPE CONSOLE>— директива создания консольного приложения

1) Директивы компилятора, разрешающие или запрещающие проверку утверждений.

По умолчанию <$C+>или <$ASSERTIONS ON>
Область действия локальная

Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует
директива <$C+>и процедура Assert генерирует исключение EAssertionFailed , если проверяемое утверждение ложно.
Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.
Директивы действуют на весь файл исходного кода независимо от того, в каком месте файла они расположены.

2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода.

По умолчанию <$I+>или <$IOCHECKS ON>
Область действия локальная

Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal . Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try . except , имеющем обработчик исключения EInOutError . Если такого блока нет, то обработка производится методом TApplication.HandleException .
Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult . Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:

AssignFile ( F,s );
Rewrite (F);

<$I+>
i:=IOResult ;
if i <> 0 then
case i of
2 : .
3 : .
end ;

В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.

3) Директивы компилятора, определяющие размер стека

По умолчанию <$M 16384,1048576>
Область действия глобальная

Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека.
Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантировано имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.
Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow . Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize директивы <$M>или параметром number директивы <$MINSTACKSIZE>.
Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number >. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.

В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.

4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах ( runtime type information — RTTI).

По умолчанию <$M->или <$ TYPEINFO OFF>
Область действия локальная

Директивы компилятора $M включают или выключают генерацию информации времени выполнения о типах ( runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published . В противном случае раздел published в классе не допускается. Класс TPersistent , являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.

5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях

По умолчанию <$Q->или <$OVERFLOWCHECKS OFF>
Область действия локальная

Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs , Sqr , Succ , Pred , Inc и Dec . После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение, то генерируется исключение EIntOverflow . Если это исключение не может быть обработано, выполнение программы завершается.
Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании.
Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.

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

По умолчанию <$R>или <$RANGECHECKS OFF>
Область действия локальная

Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError . Если оно не может быть перехвачено, выполнение программы завершается.
Проверка диапазона длинных строк типа Long strings не производится.
Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.

6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows . По умолчанию расширение файлов ресурсов — .RES.
В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories / Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.
При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл . pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и генерируется исключение EResNotFound .


Все установленные в настройках опции компиляции можно вставить непосредственно в текст программы нажав клавиши Ctrl-O , O

Как сделать свои собственные сообщения при компилляции ?

destructor TumbSelectionTempTable.Destroy ;
begin
// Clear the temp tables.
<$MESSAGE Warn ' - remember to free all allocated objects'>
ClearAllOuterWorldFold ;
if FSubjectsTempTableCreated then
DropTempTable ( FTableName );

FOuterWorldsFolded.Free ;
FQuery.Free ;
inherited ;
end ;

Работает только в Дельфи 6/7

Как узнать версию компилятора?

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

В Дельфи предопределены специальные константы компиляции для этого:

Ver80 — Дельфи 1
Ver90 — Дельфи 2
Ver93 — С Buider 1
Ver100 — Дельфи 3
Ver110 — С Buider 3
Ver120 — Дельфи 4
Ver125 — С Buider 4
Ver130 — Дельфи 5
Ver140 — Дельфи 6
Ver150 — Дельфи 7

procedure TForm1.Button2Click( Sender : TObject );
const Version=

Идентификаторы директивы компилятора Delphi $ WARN

В Delphi есть директива компилятора $ WARN, которая позволяет выборочно включать или отключать определенные предупреждения. Файл справки Delphi 2009 описывает синтаксис:

Но он отображает только идентификаторы для 6 предупреждений.

Я хотел бы иметь полный список всех предупреждающих идентификаторов. В частности, я хочу знать идентификаторы для неявных строковых предупреждений о переносе W1057 и W1058 в Delphi 2009.

I managed to guess the one for implicit Ansi->Unicode casts (W1057):

Гуглинг за это нашел меня другой:

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

$Warnings — Директива компилятора Delphi

Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес

Репутация: 14
Всего: 115

Профиль
Группа: Участник
Сообщений: 291
Регистрация: 17.3.2003

Репутация: нет
Всего: 4

директивы условной компиляции
<$C+>и <$C->— директивы проверки утверждений
<$I+>и <$I->— директивы контроля ввода/вывода
<$M>и <$S>— директивы, определяющие размер стека

<$M+>и <$M->— директивы информации времени выполнения о типах
<$Q+>и <$Q->— директивы проверки переполнения целочисленных операций

<$R>— директива связывания ресурсов

<$R+>и <$R->— директивы проверки диапазона

<$APPTYPE CONSOLE>— директива создания консольного приложения

1) Директивы компилятора, разрешающие или запрещающие проверку утверждений.

По умолчанию <$C+>или

Область действия локальная

Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует
директива <$C+>и процедура Assert генерирует исключение EAssertionFailed, если проверяемое утверждение ложно.

Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.

Директивы действуют на весь файл исходного кода независимо от того, в каком месте файла они расположены.

2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода.

По умолчанию <$I+>или

Область действия локальная

Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal. Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется
исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try. except, имеющем обработчик исключения EInOutError. Если такого блока нет, то обработка производится методом TApplication.HandleException.

Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult. Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:

В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.

3) Директивы компилятора, определяющие размер стека

Область действия глобальная

Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека.
Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантировано имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может
выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.

Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow. Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize
директивы <$M>или параметром number директивы <$MINSTACKSIZE>.

Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number>. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.

В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.

4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах (runtime type information — RTTI).

По умолчанию <$M->или

Область действия локальная

Директивы компилятора $I включают или выключают генерацию информации времени выполнения о типах (runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published. В противном
случае раздел published в классе не допускается. Класс TPersistent, являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.

5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях

По умолчанию <$Q->или

Область действия локальная

Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs, Sqr, Succ, Pred, Inc и Dec. После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение,
то генерируется исключение EIntOverflow. Если это исключение не может быть обработано, выполнение программы завершается.

Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании.
Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.

6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в
выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.

При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и генерируется исключение EResNotFound.

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

По умолчанию <$R->или

Область действия локальная

Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования
диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError. Если оно не может быть перехвачено, выполнение программы завершается.

Проверка диапазона длинных строк типа Long strings не производится.
Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.

8) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES.
В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.

При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и генерируется исключение EResNotFound.

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

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

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

Для начала, рассмотрим очень простой код, который вы можете повторить в Delphi за несколько секунд:

Теперь нажмите F9 и проверьте, что написано в отладчике в «Events»:

Разберемся с тем, что мы только что написали.

$IFDEF — это директива компилятора;

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

Процедура отправляет строку в отладчик для отображения.

Завершает условную компиляцию, инициированную последней директивой <$IFxxx>(почему не <$IFDEF>— смотрим далее).

Таким образом, используя директивы и мы указали компилятору дословно следующее: если где-либо по ходу компиляции был встречено условное определение DEBUG, то надо выполнить OutputDebugString.

Где определено условное определение DEBUG? Конкретно в этом случае, символ DEBUG можно найти, если зайти в настройки проекта: Project -> Options ->Delphi Compiler :

Здесь же можно определить и свои собственные символы. Давайте, например, добавим свой символ условной компиляции TEST. Для этого открываем диалоговое окно редактирования символов условной компиляции (жмем кнопку «…» в строке «Conditional defines») и заносим наш символ в список:

Теперь изменим наш код, приведенный в начале статьи, чтобы он работал с нашим символом условной компиляции:

Теперь можете снова запустить приложения в режиме отладки и посмотреть, что в Events появится строка «TEST IS ON».

Сейчас мы с вами рассмотрели самый простой способ использования условной компиляции в Delphi — использование директив и , а также определение собственного символа условной компиляции через свойства проекта. Вместе с этим, определить (включить) свой символ условной компиляции можно и в коде программы. Для этого используется директива компилятора . Воспользуемся этой директивой:

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

и убедиться, что символ DEBUG выключен, а в окне Events не появится строка «debug is on».

Двигаемся далее. Что делать, если нам необходимо вывести строку не когда символ включен, а именно тогда, когда он выключен? Здесь, опять же, есть варианты. Короткий вариант — воспользоваться директивой противоположной — она называется и код между и выполняется, если символ выключен:

Второй вариант — использование директивы , если в зависимости от состояния символа условной компиляции вам надо выполнять различные участки кода:

Соответственно, нет необходимости далее повторять этот же участок кода с использованием — работать будет, но прямо противоположно.

Также следует обратить внимание на то, что все условные символы оцениваются в Delphi, когда вы выполняете Build проекта. Справка Delphi рекомендует для надежности пользоваться командой Project -> Build All Projects, чтобы быть уверенным, что все символы условной компиляции определены верно.

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

Например, символ условной компиляции VER330 определен для Delphi 10.3 Rio и с его помощью можно определить какой код должен или не должен выполняться, в случае, если версия компилятора Delphi — 33. Например, воспользуемся фичей Delphi 10.3 Rio под названием Inline Variable Declaration:

Сразу может возникнуть вопрос: как сделать так, чтобы приведенный выше код сработал не только в Delphi 10.3 Rio, но и в последующих версиях?
Это можно сделать воспользовавшись, например, такой конструкцией:

Здесь мы уже воспользовались директивой с помощью которой проверили значение константы CompilerVersion, которая находится в модуле System.

Здесь же стоит обратить внимание и на окончание блока — мы использовали директиву , как того требовала Delphi до версии Delphi XE4:

  • для директивы $IFDEF должна быть определена директива $ENDIF
  • для директивы $IF должна быть определена директива $IFEND

В XE4 нам разрешили использовать для закрытия блоков <$IF>, и . Однако, если у вас возникают проблемы при использовании связки и , то вы можете использовать специальную директиву , чтобы потребовать использовать для именно <$IFEND>:

Теперь, если в коде выше использовать директиву $ENDIF, то получим сообщение об ошибке:

Директиву , кстати, можно использовать и с другими константами проекта, например, так:

Так как наша константа Version содержит значение 2, то выполнится участок кода расположенный после . Можете сменить значение константы Version на 1, чтобы убедиться, что выполнится участок кода, где определена переменная s.

Как я сказал выше, в Delphi есть целый набор предопределенных символов условной компиляции. Ознакомиться со всеми этими символами вы можете на этой странице справки по Delphi.

  1. Использование условной компиляции позволяет нам выполнять тот или иной код, в зависимости от того, какие константы и символы условной компиляции определены или не определены в проекте.
  2. Используя предопредленные символы условной компиляции можно указывать Delphi какой код необходимо выполнить, например, если программа собирается под Android, или, если поддерживается архитектура x64 и т.д.
  3. Директива $IF может использоваться с различными константами, в том числе и определенными самим разработчиком.

При подготовке статьи использовалась следующая информация официальной справки по Delphi:

Директива компилятора региона Delphi — файлы с совместимостью в обратном направлении?

Учитывая желание использовать полезную директиву компилятора Region в файлах модулей, какой лучший подход позволяет использовать эти же устройства в предыдущих версиях Delphi? Похоже, что нет «приличного» подхода. (Желаемая версия IDE — Delphi 7)

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

Я полагаю, что препроцессор можно было бы написать, чтобы прокомментировать все директивы Region/EndRegion, если используется версия Delphi, которая не поддерживает регионы .. и затем добавляет обратно для более поздних версий?

Я не на 100% перешел на Delphi 2009 и должен поддерживать несколько версий IDE.

Создан 18 апр. 09 2009-04-18 23:34:48 Darian Miller

2 ответа

Я предполагаю, что D7 не хочет переписывать <$ REGION>или <$ ENDREGION>? У меня установлен только D2007/9 и не могу это проверить.

D2009 редактор создает область, как и ожидалось. D7 должен игнорировать $ REGION/$ ENDREGION, если «undef» не определен.

Создан 19 апр. 09 2009-04-19 07:14:16 gabr

+1. Положите на одну строку и создайте с помощью кода или живого шаблона, это не убивает чистоты и не требует больше усилий писать. – mghie 19 апр. 09 2009-04-19 10:36:49

Это работает . и будет отмечен как ответ, как указано в первоначальном вопросе. Мой реальный ответ — удалить Регионы на данный момент и переключить все на 2009, как позволяет время. – Darian Miller 22 апр. 09 2009-04-22 02:38:03

Есть несколько компонентов для улучшения редактора Delphi (7), которые обеспечивают что-то вроде этого. Думаю GExperts.

Если вы в порядке с вашим кодом, вы можете рассмотреть <$ I>, чтобы разделить большие файлы.

Создан 20 апр. 09 2009-04-20 07:39:57 Stijn Sanders

. или просто разделить устройство на несколько единиц! О директиве $ INCLUDE, из моего эксперимента, $ I не работает в среде Delphi. Например, в навигаторе кода есть проблемы с просмотром кода во вложенных файлах. Нет проблем с компилятором, но с Delphi IDE. Напротив, у Lazarus нет проблем при использовании нескольких файлов INCLUDEd и обрабатывать их как обычные .pas-файлы. – Arnaud Bouchez 13 мар. 15 2015-03-13 08:38:37

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
DriveSoftware
Дата 22.1.2004, 14:05 (ссылка) | (нет голосов) Загрузка .